| | |
| | | import React, {Component} from 'react' |
| | | import PropTypes from 'prop-types' |
| | | import { is, fromJS } from 'immutable' |
| | | import { Form, Row, Col, Input, Select, InputNumber, Radio, Tooltip, Cascader, Modal } from 'antd' |
| | | import { Form, Row, Col, Input, Select, InputNumber, Radio, Tooltip, Cascader, Modal, Checkbox, Popover } from 'antd' |
| | | import { QuestionCircleOutlined } from '@ant-design/icons' |
| | | |
| | | import { getColumnForm } from './formconfig' |
| | | import { formRule } from '@/utils/option.js' |
| | | import './index.scss' |
| | | |
| | | const { TextArea } = Input |
| | |
| | | picture: ['label', 'field', 'type', 'Align', 'Hide', 'IsSort', 'Width', 'fieldlength', 'blacklist', 'scale', 'lenWidRadio', 'backgroundSize', 'span'], |
| | | video: ['label', 'field', 'type', 'Align', 'Hide', 'startTime', 'Width', 'fieldlength', 'blacklist', 'aspectRatio'], |
| | | colspan: ['label', 'type', 'Align', 'Hide', 'blacklist'], |
| | | custom: ['label', 'type', 'Align', 'Hide', 'Width', 'blacklist'], |
| | | custom: ['label', 'type', 'Align', 'Width', 'blacklist'], |
| | | action: ['label', 'type', 'Align', 'Width'], |
| | | formula: ['label', 'type', 'Align', 'Hide', 'Width', 'prefix', 'postfix', 'eval', 'formula', 'blacklist'], |
| | | index: ['label', 'type', 'Align', 'Width'] |
| | |
| | | |
| | | class NormalTableColumn extends Component { |
| | | static propTpyes = { |
| | | visible: PropTypes.bool, |
| | | column: PropTypes.object, |
| | | fields: PropTypes.array, |
| | | submitCol: PropTypes.func, // 提交事件 |
| | |
| | | visible: false, |
| | | formlist: null |
| | | } |
| | | |
| | | record = null |
| | | |
| | | UNSAFE_componentWillReceiveProps (nextProps) { |
| | | if (nextProps.column && !is(fromJS(this.props.column), fromJS(nextProps.column))) { |
| | |
| | | }) |
| | | |
| | | let formlist = getColumnForm(column, fields) |
| | | let _options = fromJS(columnTypeOptions[column.type]).toJS() |
| | | if (column.type === 'text' || column.type === 'number') { |
| | | if (column.perspective === 'linkmenu') { |
| | | _options.push('linkmenu', 'linkfields', 'open') |
| | | } else if (column.perspective === 'linkurl') { |
| | | _options.push('linkurl', 'linkfields', 'open') |
| | | } |
| | | } |
| | | |
| | | this.record = {} |
| | | |
| | | formlist.forEach(item => { |
| | | this.record[item.key] = item.initVal |
| | | }) |
| | | |
| | | let _options = this.getOptions() |
| | | |
| | | this.setState({ |
| | | visible: true, |
| | | type: column.type, |
| | | formlist: formlist.map(item => { |
| | | item.hidden = !_options.includes(item.key) |
| | | |
| | | if (item.key === 'formula') { |
| | | item.fields = this.props.fields.map(col => col.field) |
| | | item.fields = item.fields.join(', ') |
| | | } else if (this.record.type === 'formula' && item.key === 'decimal') { |
| | | item.required = false |
| | | } |
| | | |
| | | return item |
| | | }) |
| | |
| | | } |
| | | } |
| | | |
| | | getOptions = () => { |
| | | let _options = fromJS(columnTypeOptions[this.record.type]).toJS() |
| | | |
| | | if (this.record.type === 'text' || this.record.type === 'number') { |
| | | if (this.record.perspective === 'linkmenu') { |
| | | _options.push('linkmenu', 'linkfields', 'open') |
| | | } else if (this.record.perspective === 'linkurl') { |
| | | _options.push('linkurl', 'linkfields', 'open') |
| | | } |
| | | } |
| | | |
| | | if (this.record.type === 'formula' && this.record.eval === 'true') { |
| | | _options.push('decimal') |
| | | } |
| | | |
| | | return _options |
| | | } |
| | | |
| | | typeChange = (key, value, option) => { |
| | | const { column } = this.props |
| | | this.record[key] = value |
| | | |
| | | if (key === 'type') { |
| | | let _options = fromJS(columnTypeOptions[value]).toJS() |
| | | let _options = this.getOptions() |
| | | |
| | | this.setState({ |
| | | type: value, |
| | | formlist: this.state.formlist.map(item => { |
| | | if (item.key === 'decimal') { |
| | | item.required = !(column.isSub || value === 'formula') |
| | | if (value === 'formula') { |
| | | this.record.decimal = '' |
| | | } |
| | | } |
| | | |
| | | item.initVal = this.record[item.key] |
| | | item.hidden = !_options.includes(item.key) |
| | | |
| | | return item |
| | |
| | | this.props.form.setFieldsValue({IsSort: 'false'}) |
| | | } else if (value === 'text' || value === 'number') { |
| | | this.props.form.setFieldsValue({perspective: ''}) |
| | | } else if (value === 'action' || value === 'colspan') { |
| | | } else if (value === 'colspan') { |
| | | this.props.form.setFieldsValue({Align: 'center'}) |
| | | } else if (value === 'index') { |
| | | this.props.form.setFieldsValue({label: '序号'}) |
| | | } |
| | | }) |
| | | } else if (key === 'field') { |
| | |
| | | values.type = 'text' |
| | | } |
| | | |
| | | if (values.type !== this.state.type) { |
| | | let _type = this.record.type |
| | | this.record.type = values.type |
| | | |
| | | if (values.type !== _type) { |
| | | values.perspective = '' |
| | | let _options = fromJS(columnTypeOptions[values.type]).toJS() |
| | | this.record.perspective = '' |
| | | |
| | | let _options = this.getOptions() |
| | | |
| | | this.setState({ |
| | | type: values.type, |
| | | formlist: this.state.formlist.map(item => { |
| | | item.initVal = this.record[item.key] |
| | | item.hidden = !_options.includes(item.key) |
| | | |
| | | return item |
| | |
| | | } |
| | | } else if (key === 'format' && value === 'percent') { |
| | | this.props.form.setFieldsValue({postfix: '%'}) |
| | | } |
| | | } |
| | | |
| | | changeRadio = (key, value) => { |
| | | if (key === 'perspective') { |
| | | let _options = fromJS(columnTypeOptions[this.state.type]).toJS() |
| | | |
| | | if (value === 'linkmenu') { |
| | | _options.push('linkmenu', 'linkfields', 'open') |
| | | } else if (value === 'linkurl') { |
| | | _options.push('linkurl', 'linkfields', 'open') |
| | | } |
| | | } else if (['perspective', 'eval'].includes(key)) { |
| | | let _options = this.getOptions() |
| | | |
| | | this.setState({ |
| | | formlist: this.state.formlist.map(item => { |
| | | item.initVal = this.record[item.key] |
| | | item.hidden = !_options.includes(item.key) |
| | | |
| | | return item |
| | |
| | | if (item.hidden || item.forbid) return |
| | | |
| | | if (item.type === 'text') { |
| | | let rules = [] |
| | | if (item.key === 'field') { |
| | | rules = [{ |
| | | pattern: /^[\u4E00-\u9FA50-9a-zA-Z_]*$/ig, |
| | | message: '字段名只允许包含数字、字母、汉字以及_' |
| | | }, { |
| | | max: formRule.input.max, |
| | | message: formRule.input.message |
| | | }] |
| | | } else if (item.key !== 'linkurl') { |
| | | rules = [{ |
| | | max: formRule.input.max, |
| | | message: formRule.input.message |
| | | }] |
| | | } |
| | | fields.push( |
| | | <Col span={12} key={index}> |
| | | <Form.Item label={item.tooltip ? |
| | |
| | | required: !!item.required, |
| | | message: '请输入' + item.label + '!' |
| | | }, |
| | | ...rules |
| | | ...item.rules |
| | | ] |
| | | })(<Input placeholder="" autoComplete="off" disabled={item.readonly} onPressEnter={this.handleSubmit} />)} |
| | | </Form.Item> |
| | |
| | | } |
| | | ] |
| | | })( |
| | | <Radio.Group onChange={(e) => {this.changeRadio(item.key, e.target.value)}}> |
| | | { |
| | | item.options.map(option => { |
| | | return ( |
| | | <Radio key={option.value} value={option.value}>{option.text}</Radio> |
| | | ) |
| | | }) |
| | | } |
| | | <Radio.Group onChange={(e) => {this.typeChange(item.key, e.target.value)}}> |
| | | {item.options.map(option => { |
| | | return (<Radio key={option.value} value={option.value}>{option.text}</Radio>) |
| | | })} |
| | | </Radio.Group> |
| | | )} |
| | | </Form.Item> |
| | | </Col> |
| | | ) |
| | | } else if (item.type === 'checkbox') { |
| | | fields.push( |
| | | <Col span={12} key={index}> |
| | | <Form.Item label={item.tooltip ? |
| | | <Tooltip placement="topLeft" title={item.tooltip}> |
| | | <QuestionCircleOutlined className="mk-form-tip" /> |
| | | {item.label} |
| | | </Tooltip> : item.label |
| | | }> |
| | | {getFieldDecorator(item.key, { |
| | | initialValue: item.initVal |
| | | })( |
| | | <Checkbox.Group> |
| | | {item.options.map(option => <Checkbox key={option.value} value={option.value}>{option.text}</Checkbox>)} |
| | | </Checkbox.Group> |
| | | )} |
| | | </Form.Item> |
| | | </Col> |
| | |
| | | </Col> |
| | | ) |
| | | } else if (item.type === 'textarea') { |
| | | fields.push( |
| | | <Col span={24} key={index} className="textarea"> |
| | | <Form.Item label={item.tooltip ? |
| | | <Tooltip placement="topLeft" title={item.tooltip}> |
| | | <QuestionCircleOutlined className="mk-form-tip" /> |
| | | {item.label} |
| | | </Tooltip> : item.label |
| | | }> |
| | | {getFieldDecorator(item.key, { |
| | | initialValue: item.initVal || '', |
| | | rules: [ |
| | | { |
| | | required: !!item.required, |
| | | message: '请输入' + item.label + '!' |
| | | } |
| | | ] |
| | | })(<TextArea rows={2} disabled={item.readonly} placeholder={item.placeholder || ''}/>)} |
| | | </Form.Item> |
| | | </Col> |
| | | ) |
| | | if (item.key === 'formula') { |
| | | fields.push( |
| | | <Col span={24} className="textarea" key={index}> |
| | | <Form.Item label={item.tooltip ? |
| | | <Tooltip placement="topLeft" title={item.tooltip}> |
| | | <QuestionCircleOutlined className="mk-form-tip" /> |
| | | {item.label} |
| | | </Tooltip> : item.label |
| | | }> |
| | | {getFieldDecorator(item.key, { |
| | | initialValue: item.initVal || '', |
| | | rules: [ |
| | | { |
| | | required: !!item.required, |
| | | message: '请输入' + item.label + '!' |
| | | } |
| | | ] |
| | | })(<TextArea autoSize={{minRows: 2}} disabled={item.readonly} placeholder={item.placeholder || ''} />)} |
| | | </Form.Item> |
| | | <Popover overlayClassName="formula-fields" placement="topLeft" title="" content={<div>{item.fields}</div>} trigger="click"> |
| | | <span className="formula-icon">字段集</span> |
| | | </Popover> |
| | | </Col> |
| | | ) |
| | | } else { |
| | | fields.push( |
| | | <Col span={24} key={index} className="textarea"> |
| | | <Form.Item label={item.tooltip ? |
| | | <Tooltip placement="topLeft" title={item.tooltip}> |
| | | <QuestionCircleOutlined className="mk-form-tip" /> |
| | | {item.label} |
| | | </Tooltip> : item.label |
| | | }> |
| | | {getFieldDecorator(item.key, { |
| | | initialValue: item.initVal || '', |
| | | rules: [ |
| | | { |
| | | required: !!item.required, |
| | | message: '请输入' + item.label + '!' |
| | | } |
| | | ] |
| | | })(<TextArea rows={2} disabled={item.readonly} placeholder={item.placeholder || ''}/>)} |
| | | </Form.Item> |
| | | </Col> |
| | | ) |
| | | } |
| | | } |
| | | }) |
| | | return fields |
| | | } |
| | | |
| | | handleSubmit = () => { |
| | | const { fields } = this.props |
| | | // 表单提交时检查输入值是否正确 |
| | | this.props.form.validateFieldsAndScroll((err, values) => { |
| | | if (!err) { |
| | | // eslint-disable-next-line |
| | | if (values.type === 'formula' && values.eval !== 'false' && /^[\u4E00-\u9FA50-9a-zA-Z_\s@\+\-\*\/]*$/ig.test(values.formula) && /[\+\-\*\/]/ig.test(values.formula)) { |
| | | let cols = [] |
| | | fields.forEach(col => { |
| | | if (/^(Int|Decimal)/ig.test(col.datatype)) { |
| | | cols.push({reg: new RegExp('@' + col.field + '@', 'ig'), value: `(@${col.field}@)`}) |
| | | } |
| | | }) |
| | | |
| | | cols.forEach(col => { |
| | | values.formula = values.formula.replace(col.reg, col.value) |
| | | }) |
| | | } |
| | | |
| | | this.props.submitCol(values, () => { |
| | | this.setState({visible: false, formlist: null}) |
| | | }) |