| | |
| | | import React, {Component} from 'react' |
| | | import PropTypes from 'prop-types' |
| | | import {connect} from 'react-redux' |
| | | import { is, fromJS } from 'immutable' |
| | | import { DndProvider } from 'react-dnd' |
| | | import HTML5Backend from 'react-dnd-html5-backend' |
| | | import moment from 'moment' |
| | | import { Button, Card, Modal, Collapse, notification, Icon, Switch } from 'antd' |
| | | import { Button, Card, Modal, Collapse, notification, Switch } from 'antd' |
| | | import { SettingOutlined } from '@ant-design/icons' |
| | | |
| | | import Api from '@/api' |
| | | import Utils from '@/utils/utils.js' |
| | |
| | | import enUS from '@/locales/en-US/model.js' |
| | | import { getModalForm } from '@/templates/zshare/formconfig' |
| | | |
| | | import ModalForm from '@/templates/zshare/modalform' |
| | | import SourceElement from '@/templates/modalconfig/dragelement/source' |
| | | import SettingForm from '@/templates/modalconfig/settingform' |
| | | import asyncComponent from '@/utils/asyncComponent' |
| | | import { SearchItems } from '@/templates/modalconfig/source' |
| | | import MKEmitter from '@/utils/events.js' |
| | | import './index.scss' |
| | | |
| | | const { Panel } = Collapse |
| | | const { confirm } = Modal |
| | | const CommonDict = sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS |
| | | const ModalForm = asyncComponent(() => import('@/templates/zshare/modalform')) |
| | | const EditComponent = asyncComponent(() => import('@/templates/zshare/editcomponent')) |
| | | const DragElement = asyncComponent(() => import('@/templates/modalconfig/dragelement')) |
| | | const FieldsComponent = asyncComponent(() => import('@/templates/sharecomponent/fieldscomponent')) |
| | |
| | | } |
| | | |
| | | state = { |
| | | menu: null, // 上级菜单,三级菜单或标签 |
| | | dict: CommonDict, // 字典 |
| | | config: null, // 页面配置,包括模板类型、模态框设置、添加表名、表单列表 |
| | | visible: false, // 表单编辑模态框,显示控制 |
| | | tableVisible: false, // 数据表字段列表模态框,显示控制 |
| | | tableColumns: [], // 表格字段名列表 |
| | | fields: null, // 表单,可选字段(去重后) |
| | | formlist: null, // 表单编辑模态框,可编辑字段 |
| | | card: null, // 编辑元素 |
| | | closeloading: false, // 菜单保存中 |
| | | settingVisible: false, // 全局配置模态框 |
| | | closeVisible: false, // 关闭模态框 |
| | | tables: [], // 可用表名 |
| | | selectedTables: [], // 已选表名 |
| | | originConfig: null, // 原始菜单 |
| | | sources: null, // 表单类型 |
| | | sqlVerifing: false, // sql验证 |
| | | openEdition: '', // 编辑版本标记,防止多人操作 |
| | | showField: false, // 显示表单字段值 |
| | | standardform: null |
| | | standardform: null, |
| | | saving: false |
| | | } |
| | | |
| | | /** |
| | |
| | | }) |
| | | } |
| | | |
| | | componentDidMount () { |
| | | MKEmitter.addListener('completeSave', this.completeSave) |
| | | MKEmitter.addListener('submitStyle', this.getStyle) |
| | | } |
| | | |
| | | /** |
| | | * @description 组件销毁,清除state更新 |
| | | */ |
| | |
| | | this.setState = () => { |
| | | return |
| | | } |
| | | MKEmitter.removeListener('completeSave', this.completeSave) |
| | | MKEmitter.removeListener('submitStyle', this.getStyle) |
| | | } |
| | | |
| | | /** |
| | |
| | | let _config = fromJS(this.state.config).toJS() |
| | | |
| | | if (list.length > _config.fields.length) { |
| | | _config.fields = list.filter(item => !item.origin) |
| | | _config.fields = list |
| | | |
| | | this.setState({ |
| | | config: _config |
| | |
| | | let _inputfields = [] |
| | | let _tabfields = [] |
| | | let _linkableFields = [] |
| | | let _linksupFields = [{ |
| | | value: '', |
| | | text: '空' |
| | | }] |
| | | let _linksupFields = [] |
| | | let standardform = null |
| | | |
| | | _inputfields = config.fields.filter(item => item.type === 'text' || item.type === 'number' || item.type === 'textarea' || item.type === 'color') |
| | | _tabfields = config.fields.filter(item => card.field !== item.field && item.hidden !== 'true' && ['text', 'number', 'select', 'link'].includes(item.type)) |
| | | _tabfields.unshift({field: '', text: '原表单'}) |
| | | |
| | | let uniq = new Map() |
| | | uniq.set(card.field, true) |
| | | let index = null |
| | | uniq.set(card.field, true) |
| | | |
| | | let _inputIndex = 1 |
| | | let _tabIndex = 1 |
| | | let _linkIndex = 1 |
| | | config.fields.forEach((item, i) => { |
| | | if (card.uuid === item.uuid) { |
| | | index = i |
| | | } |
| | | if (item.type !== 'select' && item.type !== 'link' && item.type !== 'radio') return |
| | | |
| | | let label = item.label || '' |
| | | if (item.field && item.field.toLowerCase() !== label.toLowerCase()) { |
| | | label = label + ' (' + item.field + ')' |
| | | } |
| | | |
| | | if (['text', 'number', 'textarea', 'color'].includes(item.type) && card.field !== item.field) { |
| | | _inputfields.push({ |
| | | field: item.field, |
| | | label: _inputIndex + '、' + label |
| | | }) |
| | | _inputIndex++ |
| | | } |
| | | if (card.field !== item.field && item.hidden !== 'true' && ['text', 'number', 'select', 'link'].includes(item.type)) { |
| | | _tabfields.push({ |
| | | field: item.field, |
| | | label: _tabIndex + '、' + label |
| | | }) |
| | | _tabIndex++ |
| | | } |
| | | |
| | | if (item.type === 'switch') { |
| | | _linksupFields.push({ |
| | | field: item.field, |
| | | label: _linkIndex + '、' + label |
| | | }) |
| | | } |
| | | |
| | | if (!['select', 'link', 'radio', 'checkcard'].includes(item.type)) return |
| | | if (item.type === 'checkcard' && item.multiple === 'true') return // 选项卡多选 |
| | | if (item.field && !uniq.has(item.field)) { |
| | | uniq.set(item.field, true) |
| | | |
| | | _linkableFields.push({ |
| | | value: item.field, |
| | | text: item.label + ' (表单)' |
| | | field: item.field, |
| | | label: _linkIndex + '、' + item.label + ' (表单)' |
| | | }) |
| | | _linksupFields.push({ |
| | | value: item.field, |
| | | text: item.label |
| | | field: item.field, |
| | | label: _linkIndex + '、' + label |
| | | }) |
| | | _linkIndex++ |
| | | } |
| | | }) |
| | | if (index !== null) { |
| | |
| | | } |
| | | } |
| | | |
| | | _tabfields.unshift({field: '', label: '原表单'}) |
| | | |
| | | componentConfig.columns.forEach(col => { |
| | | if (col.field && !uniq.has(col.field)) { |
| | | uniq.set(col.field, true) |
| | | |
| | | _linkableFields.push({ |
| | | value: col.field, |
| | | text: col.label + ' (显示列)' |
| | | field: col.field, |
| | | label: _linkIndex + '、' + col.label + ' (显示列)' |
| | | }) |
| | | _linkIndex++ |
| | | } |
| | | }) |
| | | |
| | |
| | | standardform, |
| | | visible: true, |
| | | card: card, |
| | | formlist: getModalForm(card, _inputfields, _tabfields, _linkableFields, _linksupFields, !!this.props.editTab) |
| | | formlist: getModalForm(card, _inputfields, _tabfields, _linkableFields, _linksupFields) |
| | | }) |
| | | } |
| | | |
| | | getStyle = (comIds, style) => { |
| | | const { config } = this.state |
| | | |
| | | if (comIds[0] !== 'form') return |
| | | |
| | | let Index = config.fields.findIndex(n => n.uuid === comIds[1]) |
| | | |
| | | if (Index === -1) return |
| | | |
| | | let _config = fromJS(config).toJS() |
| | | |
| | | _config.fields[Index].style = style |
| | | |
| | | this.setState({ |
| | | config: _config |
| | | }) |
| | | } |
| | | |
| | |
| | | this.formRef.handleConfirm().then(res => { |
| | | let _config = fromJS(this.state.config).toJS() |
| | | let fieldrepet = false // 字段重复 |
| | | let labelrepet = false // 提示文字重复 |
| | | |
| | | _config.fields = _config.fields.map(item => { |
| | | if (item.uuid !== res.uuid && res.field && item.field && item.field.toLowerCase() === res.field.toLowerCase()) { |
| | | fieldrepet = true |
| | | } else if (res.label && item.uuid !== res.uuid && item.label === res.label) { |
| | | labelrepet = true |
| | | } |
| | | |
| | | if (item.uuid === res.uuid) { |
| | | if (item.style) { |
| | | res.style = item.style |
| | | } |
| | | return res |
| | | } else { |
| | | return item |
| | |
| | | duration: 10 |
| | | }) |
| | | return |
| | | } else if (labelrepet) { |
| | | notification.warning({ |
| | | top: 92, |
| | | message: '名称已存在!', |
| | | duration: 10 |
| | | }) |
| | | return |
| | | } |
| | | |
| | | _config.fields = _config.fields.filter(item => !item.origin) |
| | | |
| | | if ((res.type === 'select' || res.type === 'multiselect' || res.type === 'link') && res.resourceType === '1' && /\s/.test(res.dataSource)) { |
| | | if (['select', 'multiselect', 'link', 'checkbox', 'radio', 'checkcard'].includes(res.type) && res.resourceType === '1' && /\s/.test(res.dataSource)) { |
| | | this.setState({ |
| | | sqlVerifing: true |
| | | }) |
| | |
| | | submitConfig = () => { |
| | | const { config } = this.state |
| | | |
| | | this.setState({originConfig: fromJS(config).toJS(), saving: true}) |
| | | this.props.handleSave(config) |
| | | |
| | | setTimeout(() => { |
| | | MKEmitter.emit('triggerMenuSave') |
| | | }, 100) |
| | | } |
| | | |
| | | clearConfig = () => { |
| | | const _this = this |
| | | let _config = {...this.state.config, fields: []} |
| | | |
| | | confirm({ |
| | | content: '确定清空表单吗?', |
| | | onOk() { |
| | | _this.setState({ config: _config }) |
| | | }, |
| | | onCancel() {} |
| | | }) |
| | | } |
| | | |
| | | completeSave = () => { |
| | | this.setState({saving: false}) |
| | | } |
| | | |
| | | cancelConfig = () => { |
| | | const { config, originConfig } = this.state |
| | | |
| | | if (!is(fromJS(config), fromJS(originConfig))) { |
| | | this.setState({ |
| | | closeVisible: true |
| | | let _this = this |
| | | confirm({ |
| | | content: '配置信息未保存,确定返回吗?', |
| | | onOk() { |
| | | _this.props.handleBack() |
| | | }, |
| | | onCancel() {} |
| | | }) |
| | | } else { |
| | | this.props.handleBack() |
| | |
| | | }) |
| | | } |
| | | |
| | | plusFields = (items) => { |
| | | let _config = fromJS(this.state.config).toJS() |
| | | |
| | | _config.fields.push(...items) |
| | | |
| | | this.setState({ |
| | | config: _config |
| | | }, () => { |
| | | if (items.length === 1 && items[0].focus) { |
| | | this.handleForm(items[0]) |
| | | } |
| | | }) |
| | | } |
| | | |
| | | render () { |
| | | const { config, dict } = this.state |
| | | const { config, dict, saving } = this.state |
| | | |
| | | return ( |
| | | <div className="modal-form-board"> |
| | |
| | | return (<SourceElement key={index} content={item}/>) |
| | | })} |
| | | </div> |
| | | <FieldsComponent |
| | | config={config} |
| | | type="form" |
| | | updatefield={this.updateConfig} |
| | | /> |
| | | <FieldsComponent config={config} type="form" plusFields={this.plusFields}/> |
| | | </Panel> |
| | | </Collapse> |
| | | </div> |
| | | <div className="setting"> |
| | | <Card title={dict['header.menu.form.configurable']} bordered={false} extra={ |
| | | <Card title="表单配置" bordered={false} extra={ |
| | | <div> |
| | | <EditComponent dict={dict} options={['form']} config={this.state.config} refresh={(res) => this.updateConfig(res.config)}/> |
| | | <Button type="primary" onClick={this.submitConfig}>{dict['model.confirm']}</Button> |
| | | <Button onClick={this.cancelConfig}>{dict['model.cancel']}</Button> |
| | | <Button type="danger" onClick={this.clearConfig}>清空</Button> |
| | | <EditComponent dict={dict} options={['form']} config={this.state.config} plusFields={this.plusFields}/> |
| | | <Button type="primary" id="save-modal-config" loading={saving} onClick={this.submitConfig}>保存</Button> |
| | | <Button onClick={this.cancelConfig}>返回</Button> |
| | | </div> |
| | | } style={{ width: '100%' }}> |
| | | <Icon type="setting" onClick={this.changeSetting} /> |
| | | <div className="ant-modal-content" style={{width: config.setting.width + '%'}}> |
| | | <SettingOutlined onClick={this.changeSetting} /> |
| | | <div className="ant-modal-content" style={{width: config.setting.width > 100 ? config.setting.width : config.setting.width + '%'}}> |
| | | <div className="ant-modal-header"> |
| | | <div className="ant-modal-title">{config.setting.title}</div> |
| | | <Button className="mk-cols-change" onClick={() => this.changecols(1)}>1列</Button> |
| | |
| | | <Modal |
| | | title={this.state.dict['model.edit']} |
| | | visible={this.state.visible} |
| | | width={850} |
| | | width={950} |
| | | maskClosable={false} |
| | | onCancel={this.editModalCancel} |
| | | onOk={this.handleSubmit} |
| | | confirmLoading={this.state.sqlVerifing} |
| | |
| | | <Modal |
| | | title={this.state.dict['model.edit']} |
| | | visible={this.state.settingVisible} |
| | | width={700} |
| | | width={850} |
| | | maskClosable={false} |
| | | onOk={this.settingSave} |
| | | onCancel={() => { this.setState({ settingVisible: false }) }} |
| | |
| | | wrappedComponentRef={(inst) => this.settingRef = inst} |
| | | /> |
| | | </Modal> |
| | | <Modal |
| | | bodyStyle={{textAlign: 'center', color: '#000000', fontSize: '16px'}} |
| | | closable={false} |
| | | maskClosable={false} |
| | | visible={this.state.closeVisible} |
| | | onCancel={() => { this.setState({closeVisible: false}) }} |
| | | footer={[ |
| | | <Button key="save" className="mk-btn mk-green" loading={this.state.closeloading} onClick={this.submitConfig}>{this.state.dict['model.save']}</Button>, |
| | | <Button key="confirm" className="mk-btn mk-yellow" onClick={this.props.handleBack}>{this.state.dict['model.notsave']}</Button>, |
| | | <Button key="cancel" onClick={() => { this.setState({closeVisible: false}) }}>{this.state.dict['model.cancel']}</Button> |
| | | ]} |
| | | destroyOnClose |
| | | > |
| | | {this.state.dict['header.menu.config.placeholder']} |
| | | </Modal> |
| | | </div> |
| | | ) |
| | | } |
| | | } |
| | | |
| | | const mapStateToProps = (state) => { |
| | | return { |
| | | menu: state.customMenu |
| | | } |
| | | } |
| | | |
| | | const mapDispatchToProps = () => { |
| | | return {} |
| | | } |
| | | |
| | | export default connect(mapStateToProps, mapDispatchToProps)(ComModalConfig) |
| | | export default ComModalConfig |