import React, {Component} from 'react'
|
import PropTypes from 'prop-types'
|
import { is, fromJS } from 'immutable'
|
import { Modal, Empty, Radio } from 'antd'
|
import { ForkOutlined } from '@ant-design/icons'
|
|
import './index.scss'
|
|
class FormFork extends Component {
|
static propTpyes = {
|
forms: PropTypes.array
|
}
|
|
state = {
|
visible: false,
|
empty: false,
|
ctrlFields: [],
|
ctrlRFields: [],
|
subFields: [],
|
subRFields: [],
|
linkFields: [],
|
tabFields: [],
|
type: '',
|
forward: 'true',
|
}
|
|
shouldComponentUpdate (nextProps, nextState) {
|
return !is(fromJS(this.state), fromJS(nextState))
|
}
|
|
trigger = () => {
|
const { forms } = this.props
|
|
let linkFields = {} // 关联菜单
|
let controlFields = {} // 控制表单
|
let fieldMap = new Map()
|
let formlist = fromJS(forms).toJS()
|
|
formlist.forEach(item => {
|
if (item.supField) { // 多层表单控制
|
if (['hint', 'split', 'formula'].includes(item.type)) {
|
item.field = item.uuid
|
}
|
let supvals = []
|
if (item.supvalue) {
|
item.supvalue.split(',').forEach(val => {
|
supvals.push(val)
|
})
|
} else {
|
supvals.push('')
|
}
|
supvals = Array.from(new Set(supvals))
|
controlFields[item.supField] = controlFields[item.supField] || []
|
controlFields[item.supField].push({field: item.field, values: supvals.join(','), type: item.type})
|
} else {
|
delete item.supField
|
delete item.supvalue
|
}
|
if (item.linkField) {
|
linkFields[item.linkField] = linkFields[item.linkField] || []
|
linkFields[item.linkField].push({field: item.field, label: item.label, uuid: item.uuid})
|
} else {
|
delete item.linkField
|
}
|
|
Object.keys(item).forEach(key => {
|
if (!['type', 'uuid', 'field', 'label', 'supField', 'supvalue', 'linkField', 'linkSubField', 'multiple', 'enter', 'tabField'].includes(key)) {
|
delete item[key]
|
}
|
})
|
|
if (!item.field) return
|
|
fieldMap.set(item.field, item)
|
})
|
|
Object.keys(controlFields).forEach(key => {
|
if (!fieldMap.has(key)) return
|
|
let supItem = fieldMap.get(key)
|
let fields = []
|
|
controlFields[key].forEach(item => {
|
if (!fieldMap.has(item.field)) return
|
|
item.label = fieldMap.get(item.field).label
|
|
fields.push(item)
|
})
|
|
if (fields.length === 0) return
|
|
supItem.controlFields = fields
|
|
fieldMap.set(key, supItem)
|
})
|
|
let _f = fromJS([...fieldMap.values()]).toJS()
|
_f.forEach(item => {
|
// 下级表单控制-字段写入
|
if (item.linkSubField && item.linkSubField.length > 0) {
|
item.subFields = []
|
if ((['select', 'radio', 'link', 'cascader'].includes(item.type) || (item.type === 'checkcard' && item.multiple !== 'true'))) {
|
item.linkSubField.forEach(m => {
|
let n = fieldMap.get(m)
|
if (n && ['text', 'number', 'textarea', 'select'].includes(n.type)) {
|
item.subFields.push({
|
uuid: n.uuid,
|
field: m,
|
label: n.label
|
})
|
}
|
})
|
} else if (item.type === 'switch') {
|
item.linkSubField.forEach(m => {
|
let n = fieldMap.get(m)
|
if (n && ['text', 'number', 'textarea', 'select'].includes(n.type)) {
|
item.subFields.push({
|
uuid: n.uuid,
|
field: m,
|
label: n.label
|
})
|
}
|
})
|
} else if (item.type === 'fileupload') {
|
item.linkSubField.forEach(m => {
|
let n = fieldMap.get(m)
|
if (n && ['text', 'number', 'textarea', 'select'].includes(n.type)) {
|
item.subFields.push({
|
uuid: n.uuid,
|
field: m,
|
label: n.label
|
})
|
}
|
})
|
} else if (item.type === 'popSelect') {
|
item.linkSubField.forEach(m => {
|
let n = fieldMap.get(m)
|
if (n && ['text', 'number', 'textarea', 'select'].includes(n.type)) {
|
item.subFields.push({
|
uuid: n.uuid,
|
field: m,
|
label: n.label
|
})
|
}
|
})
|
}
|
|
if (item.subFields.length === 0) {
|
delete item.subFields
|
}
|
}
|
|
if (linkFields[item.field]) {
|
item.linkFields = linkFields[item.field]
|
}
|
|
if (item.enter === 'tab' || item.enter === 'sub') {
|
if (item.tabField) {
|
if (!fieldMap.has(item.tabField)) {
|
delete item.tabField
|
} else {
|
item.tabLabel = fieldMap.get(item.tabField).label
|
}
|
} else {
|
delete item.tabField
|
}
|
} else {
|
delete item.tabField
|
}
|
|
if (item.supField) {
|
if (!fieldMap.has(item.supField)) {
|
delete item.supField
|
delete item.supvalue
|
} else {
|
item.supLabel = fieldMap.get(item.supField).label
|
}
|
}
|
if (item.linkField) {
|
if (!fieldMap.has(item.linkField)) {
|
item.linkLabel = '字段集'
|
} else {
|
item.linkLabel = fieldMap.get(item.linkField).label
|
}
|
}
|
|
delete item.enter
|
delete item.multiple
|
delete item.linkSubField
|
|
fieldMap.set(item.field, item)
|
})
|
|
let _t = fromJS([...fieldMap.values()]).toJS()
|
|
_t.forEach(item => {
|
if (item.subFields) {
|
item.subFields.forEach(cell => {
|
let _cell = fieldMap.get(cell.field)
|
|
_cell.resubFields = _cell.resubFields || []
|
|
_cell.resubFields.push({
|
uuid: item.uuid,
|
field: item.field,
|
label: item.label
|
})
|
|
fieldMap.set(cell.field, _cell)
|
})
|
}
|
})
|
|
let _n = [...fieldMap.values()]
|
|
let ctrlFields = []
|
let ctrlRFields = []
|
let subFields = []
|
let subRFields = []
|
let _linkFields = []
|
let tabFields = []
|
|
_n.forEach(cell => {
|
if (cell.controlFields) {
|
ctrlFields.push({
|
field: cell.field,
|
label: cell.label,
|
children: cell.controlFields.map(m => {
|
return {
|
field: ['hint', 'split', 'formula'].includes(m.type) ? '' : m.field,
|
label: m.label,
|
tail: `${m.values}`
|
}
|
})
|
})
|
}
|
if (cell.supField) {
|
ctrlRFields.push({
|
field: ['hint', 'split', 'formula'].includes(cell.type) ? '' : cell.field,
|
label: cell.label,
|
children: [{
|
field: cell.supField,
|
label: cell.supLabel,
|
tail: `${cell.supvalue}`
|
}]
|
})
|
}
|
|
if (cell.subFields) {
|
subFields.push({
|
field: cell.field,
|
label: cell.label,
|
children: cell.subFields
|
})
|
}
|
if (cell.resubFields) {
|
subRFields.push({
|
field: cell.field,
|
label: cell.label,
|
children: cell.resubFields
|
})
|
}
|
if (cell.linkFields) {
|
_linkFields.push({
|
field: cell.field,
|
label: cell.label,
|
children: cell.linkFields
|
})
|
}
|
if (cell.tabField) {
|
tabFields.push({
|
field: cell.field,
|
label: cell.label,
|
children: [{
|
field: cell.tabField,
|
label: cell.tabLabel,
|
}]
|
})
|
}
|
})
|
|
let type = ''
|
if (ctrlFields.length > 0) {
|
type = 'ctrl'
|
} else if (subFields.length > 0) {
|
type = 'input'
|
} else if (_linkFields.length > 0) {
|
type = 'link'
|
} else if (tabFields.length > 0) {
|
type = 'switch'
|
}
|
|
this.setState({
|
type,
|
forward: 'true',
|
empty: type === '',
|
ctrlFields,
|
ctrlRFields,
|
subFields,
|
subRFields,
|
linkFields: _linkFields,
|
tabFields,
|
visible: true
|
})
|
}
|
|
getcontent = () => {
|
const { ctrlFields, ctrlRFields, subFields, subRFields, linkFields, tabFields, visible, type, forward } = this.state
|
|
if (!visible) return null
|
|
let header = <div className="fork-tabs">
|
{ctrlFields.length ? <div onClick={() => this.setState({type: 'ctrl', forward: 'true'})} className={'tab-item' + (type === 'ctrl' ? ' active' : '')}>表单控制</div> : null}
|
{subFields.length ? <div onClick={() => this.setState({type: 'input', forward: 'true'})} className={'tab-item' + (type === 'input' ? ' active' : '')}>表单填充</div> : null}
|
{linkFields.length ? <div onClick={() => this.setState({type: 'link', forward: 'true'})} className={'tab-item' + (type === 'link' ? ' active' : '')}>表单关联</div> : null}
|
{tabFields.length ? <div onClick={() => this.setState({type: 'switch', forward: 'true'})} className={'tab-item' + (type === 'switch' ? ' active' : '')}>表单切换</div> : null}
|
</div>
|
|
let items = []
|
|
if (type === 'ctrl') {
|
if (forward === 'true') {
|
items = ctrlFields
|
} else {
|
items = ctrlRFields
|
}
|
} else if (type === 'input') {
|
if (forward === 'true') {
|
items = subFields
|
} else {
|
items = subRFields
|
}
|
} else if (type === 'link') {
|
items = linkFields
|
} else if (type === 'switch') {
|
items = tabFields
|
}
|
|
let content = items.map((item, i) => {
|
return <div className="fork-item-wrap" key={i}>
|
<div className="fork-left">
|
<div className="fork-item">
|
<span>{item.label}</span>
|
<span>{item.field}</span>
|
</div>
|
</div>
|
<div className="fork-right">
|
{item.children.map((cell, n) => <div className="fork-item" key={n}>
|
<span>{cell.label}</span>
|
<span>{cell.field}</span>
|
{cell.tail ? <span className="fork-tail">{cell.tail}</span> : null}
|
</div>)}
|
</div>
|
</div>
|
})
|
|
return <div>
|
{header}
|
{type === 'ctrl' || type === 'input' ? <div className="forward-wrap"><Radio.Group value={forward} onChange={(e) => this.setState({forward: e.target.value})}>
|
<Radio value="true">正向</Radio>
|
<Radio value="false">反向</Radio>
|
</Radio.Group></div> : null}
|
<div className="fork-wrap">
|
{content}
|
</div>
|
</div>
|
}
|
|
render() {
|
const { visible, empty } = this.state
|
|
return (
|
<>
|
<ForkOutlined title="表单关系图" onClick={this.trigger}/>
|
<Modal
|
title={empty ? '表单关系图' : ''}
|
wrapClassName="form-fork-modal mk-scroll-modal"
|
visible={visible}
|
width={900}
|
maskClosable={true}
|
closable={false}
|
cancelText="关闭"
|
onOk={() => { this.setState({ visible: false })}}
|
onCancel={() => { this.setState({ visible: false })}}
|
destroyOnClose
|
>
|
{empty ? <Empty description="无表单关联信息。" /> : this.getcontent()}
|
</Modal>
|
</>
|
)
|
}
|
}
|
|
export default FormFork
|