| | |
| | | |
| | | let formItem = null |
| | | if (card.type === 'text' || card.type === 'number') { |
| | | formItem = (<div className="am-list-item"><div className="am-list-line"><div className="am-input-label">{card.label}</div><div className={'am-input-control ' + card.cursor}>{card.initval}</div>{card.scan === 'true' ? <div className="am-list-extra"><Icon type="scan" /></div> : null}</div></div>) |
| | | formItem = (<div className="am-list-item"><div className="am-list-line"><div className="am-input-label">{card.label}</div><div className={'am-input-control ' + card.cursor}>{card.initval}</div>{card.scan && card.scan !== 'false' ? <div className="am-list-extra"><Icon type="scan" /></div> : null}</div></div>) |
| | | } else if (card.type === 'number') { |
| | | formItem = (<div className="am-list-item"><div className="am-list-line"><div className="am-input-label">{card.label}</div><div className={'am-input-control ' + card.cursor}>{card.initval}</div></div></div>) |
| | | } else if (card.type === 'select' || card.type === 'link') { |
| | |
| | | floor: card.floor, |
| | | width: card.width || 24, |
| | | subtype: card.subtype, |
| | | wrap: { height: 50, title: 'NavBar', back: 'true', logout: 'false' }, |
| | | wrap: { type: 'navbar', height: 50, title: 'NavBar', back: 'true', search: 'false', logout: 'false' }, |
| | | style: {borderBottomColor: '#bcbcbc', borderBottomWidth: '1px', paddingLeft: '10px', paddingRight: '10px', lineHeight: '2.8', fontSize: '18px' }, |
| | | } |
| | | |
| | |
| | | } |
| | | } |
| | | |
| | | setSearch = () => { |
| | | |
| | | } |
| | | |
| | | render() { |
| | | const { card } = this.state |
| | | |
| | |
| | | <div className="am-navbar-left"> |
| | | {card.wrap.back !== 'false' ? <Icon type="left" /> : null} |
| | | </div> |
| | | <div className="am-navbar-title">{card.wrap.title || ''}</div> |
| | | {card.wrap.type !== 'search' ? |
| | | <div className="am-navbar-title">{card.wrap.title || ''}</div> : |
| | | <div className="am-navbar-search" onDoubleClick={this.setSearch}><div className="search-bar"><Icon type="search" /></div></div> |
| | | } |
| | | <div className="am-navbar-right"> |
| | | {card.wrap.logout === 'true' ? <span>退出</span> : null} |
| | | {card.wrap.search === 'true' ? <Icon type="search" onDoubleClick={this.setSearch}/> : null} |
| | | {card.wrap.logout === 'true' ? <Icon type="ellipsis" /> : null} |
| | | </div> |
| | | </div> |
| | | </div> |
| | |
| | | font-style: inherit; |
| | | font-weight: inherit; |
| | | .am-navbar-left { |
| | | flex: 1; |
| | | width: 30px; |
| | | text-align: left; |
| | | color: #1890ff; |
| | | } |
| | |
| | | font-weight: inherit; |
| | | flex: 1; |
| | | } |
| | | .am-navbar-right { |
| | | .am-navbar-search { |
| | | flex: 1; |
| | | padding: 0 5px; |
| | | .search-bar { |
| | | height: 35px; |
| | | line-height: 35px; |
| | | padding: 0 10px; |
| | | color:rgba(0, 0, 0, 0.65); |
| | | border: 1px solid #e8e8e8; |
| | | background: #efefef; |
| | | border-radius: 4px; |
| | | position: relative; |
| | | top: 50%; |
| | | transform: translateY(-50%); |
| | | cursor: pointer; |
| | | } |
| | | } |
| | | .am-navbar-right { |
| | | text-align: right; |
| | | color: #1890ff; |
| | | min-width: 30px; |
| | | .anticon-search { |
| | | margin-right: 5px; |
| | | padding: 5px; |
| | | cursor: pointer; |
| | | } |
| | | } |
| | | } |
| | | } |
| | |
| | | wrapClassName="popview-modal" |
| | | title="导航栏设置" |
| | | visible={visible} |
| | | width={600} |
| | | width={750} |
| | | maskClosable={false} |
| | | okText={dict['model.submit']} |
| | | onOk={this.verifySubmit} |
| | |
| | | inputSubmit: PropTypes.func // 回车事件 |
| | | } |
| | | |
| | | state = {} |
| | | state = { |
| | | type: this.props.wrap.type || 'navbar' |
| | | } |
| | | |
| | | handleConfirm = () => { |
| | | // 表单提交时检查输入值是否正确 |
| | |
| | | render() { |
| | | const { wrap } = this.props |
| | | const { getFieldDecorator } = this.props.form |
| | | const { type } = this.state |
| | | const formItemLayout = { |
| | | labelCol: { |
| | | xs: { span: 24 }, |
| | |
| | | <div className="model-menu-setting-form"> |
| | | <Form {...formItemLayout}> |
| | | <Row gutter={24}> |
| | | <Col span={22}> |
| | | <Col span={12}> |
| | | <Form.Item label="类型"> |
| | | {getFieldDecorator('type', { |
| | | initialValue: wrap.type || 'navbar' |
| | | })( |
| | | <Radio.Group onChange={(e) => this.setState({type: e.target.value})}> |
| | | <Radio value="navbar">导航栏</Radio> |
| | | <Radio value="search">搜索栏</Radio> |
| | | </Radio.Group> |
| | | )} |
| | | </Form.Item> |
| | | </Col> |
| | | {type === 'navbar' ? <Col span={12}> |
| | | <Form.Item label="标题"> |
| | | {getFieldDecorator('title', { |
| | | initialValue: wrap.title || '' |
| | | })(<Input placeholder={''} autoComplete="off" onPressEnter={this.handleSubmit} />)} |
| | | </Form.Item> |
| | | </Col> |
| | | <Col span={22}> |
| | | </Col> : null} |
| | | <Col span={12}> |
| | | <Form.Item label="高度"> |
| | | {getFieldDecorator('height', { |
| | | initialValue: wrap.height || 50, |
| | |
| | | })(<InputNumber min={30} max={200} precision={0} onPressEnter={this.handleSubmit} />)} |
| | | </Form.Item> |
| | | </Col> |
| | | <Col span={24}> |
| | | <Col span={12}> |
| | | <Form.Item label="返回"> |
| | | {getFieldDecorator('back', { |
| | | initialValue: wrap.back || 'true' |
| | | })( |
| | | <Radio.Group> |
| | | <Radio value="true">显示</Radio> |
| | | <Radio value="false">不显示</Radio> |
| | | <Radio value="false">隐藏</Radio> |
| | | </Radio.Group> |
| | | )} |
| | | </Form.Item> |
| | | </Col> |
| | | <Col span={24}> |
| | | {type === 'navbar' ? <Col span={12}> |
| | | <Form.Item label="搜索"> |
| | | {getFieldDecorator('search', { |
| | | initialValue: wrap.search || 'false' |
| | | })( |
| | | <Radio.Group> |
| | | <Radio value="true">显示</Radio> |
| | | <Radio value="false">隐藏</Radio> |
| | | </Radio.Group> |
| | | )} |
| | | </Form.Item> |
| | | </Col> : null} |
| | | <Col span={12}> |
| | | <Form.Item label={ |
| | | <Tooltip placement="topLeft" title="点击退出时,返回第一个页面。"> |
| | | <Icon type="question-circle" /> |
| | |
| | | })( |
| | | <Radio.Group> |
| | | <Radio value="true">显示</Radio> |
| | | <Radio value="false">不显示</Radio> |
| | | <Radio value="false">隐藏</Radio> |
| | | </Radio.Group> |
| | | )} |
| | | </Form.Item> |
New file |
| | |
| | | import React, {Component} from 'react' |
| | | import { is, fromJS } from 'immutable' |
| | | |
| | | import MKEmitter from '@/utils/events.js' |
| | | import ModalConfig from '@/mob/modalconfig' |
| | | |
| | | class ModalController extends Component { |
| | | state = { |
| | | btn: null, |
| | | config: null, |
| | | visible: false |
| | | } |
| | | |
| | | shouldComponentUpdate (nextProps, nextState) { |
| | | return !is(fromJS(this.state), fromJS(nextState)) |
| | | } |
| | | |
| | | componentDidMount () { |
| | | MKEmitter.addListener('changeModal', this.initConfig) |
| | | } |
| | | |
| | | /** |
| | | * @description 组件销毁,清除state更新,清除快捷键设置 |
| | | */ |
| | | componentWillUnmount () { |
| | | this.setState = () => { |
| | | return |
| | | } |
| | | MKEmitter.removeListener('changeModal', this.initConfig) |
| | | } |
| | | |
| | | initConfig = (config, btn) => { |
| | | this.setState({ |
| | | visible: true, |
| | | config: fromJS(config).toJS(), |
| | | btn: fromJS(btn).toJS() |
| | | }) |
| | | } |
| | | |
| | | handleBack = () => { |
| | | this.setState({ |
| | | visible: false, |
| | | config: null, |
| | | btn: null |
| | | }) |
| | | } |
| | | |
| | | handleSave = (modal) => { |
| | | const { config, btn } = this.state |
| | | MKEmitter.emit('submitModal', config, btn, modal) |
| | | } |
| | | |
| | | render () { |
| | | const { config, btn, visible } = this.state |
| | | |
| | | if (!visible) return null |
| | | |
| | | return ( |
| | | <ModalConfig btn={btn} componentConfig={config} handleBack={this.handleBack} handleSave={this.handleSave}/> |
| | | ) |
| | | } |
| | | } |
| | | |
| | | export default ModalController |
New file |
| | |
| | | import React, {Component} from 'react' |
| | | import PropTypes from 'prop-types' |
| | | import { is, fromJS } from 'immutable' |
| | | import { DndProvider } from 'react-dnd' |
| | | import HTML5Backend from 'react-dnd-html5-backend' |
| | | import moment from 'moment' |
| | | import { Button, Modal, Collapse, notification, Switch, Icon } from 'antd' |
| | | |
| | | import Api from '@/api' |
| | | import Utils from '@/utils/utils.js' |
| | | import zhCN from '@/locales/zh-CN/model.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 './source' |
| | | import './index.scss' |
| | | |
| | | const { Panel } = Collapse |
| | | const { confirm } = Modal |
| | | const CommonDict = sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS |
| | | const PasteComponent = asyncComponent(() => import('./pastecomponent')) |
| | | const DragElement = asyncComponent(() => import('@/mob/components/formdragelement')) |
| | | const FieldsComponent = asyncComponent(() => import('@/templates/sharecomponent/fieldscomponent')) |
| | | |
| | | class ComModalConfig extends Component { |
| | | static propTpyes = { |
| | | btn: PropTypes.object, |
| | | handleSave: PropTypes.func, |
| | | handleBack: PropTypes.func |
| | | } |
| | | |
| | | state = { |
| | | 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 |
| | | } |
| | | |
| | | /** |
| | | * @description 数据预处理 |
| | | */ |
| | | UNSAFE_componentWillMount () { |
| | | const { btn } = this.props |
| | | |
| | | let _config = btn.modal |
| | | _config.version = '1.0' |
| | | |
| | | this.setState({ |
| | | config: _config, |
| | | originConfig: fromJS(_config).toJS() |
| | | }) |
| | | } |
| | | |
| | | /** |
| | | * @description 组件销毁,清除state更新 |
| | | */ |
| | | componentWillUnmount () { |
| | | this.setState = () => { |
| | | return |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * @description 表单变化 |
| | | * 1、表单拖拽添加时,检查是否存在示例表单,如存在则去除示例 |
| | | * 2、表单移动后,保存移动后的顺序 |
| | | * 3、新增表单时,直接打开编辑框 |
| | | */ |
| | | handleList = (list, newcard) => { |
| | | let _config = fromJS(this.state.config).toJS() |
| | | |
| | | if (list.length > _config.fields.length) { |
| | | _config.fields = list.filter(item => !item.origin) |
| | | |
| | | this.setState({ |
| | | config: _config |
| | | }, () => { |
| | | this.handleForm(newcard) |
| | | }) |
| | | } else { |
| | | _config.fields = list |
| | | this.setState({config: _config}) |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * @description 表单编辑 |
| | | * 1、显示编辑弹窗-visible |
| | | * 2、保存编辑项-card |
| | | * 3、设置编辑参数项-formlist |
| | | */ |
| | | handleForm = (_card) => { |
| | | const { componentConfig } = this.props |
| | | const { config } = this.state |
| | | let card = fromJS(_card).toJS() |
| | | let _inputfields = [] |
| | | let _tabfields = [] |
| | | let _linkableFields = [] |
| | | let _linksupFields = [{ |
| | | value: '', |
| | | text: '空' |
| | | }] |
| | | 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 |
| | | config.fields.forEach((item, i) => { |
| | | if (card.uuid === item.uuid) { |
| | | index = i |
| | | } |
| | | if (item.type !== 'select' && item.type !== 'link' && item.type !== 'radio') return |
| | | if (item.field && !uniq.has(item.field)) { |
| | | uniq.set(item.field, true) |
| | | |
| | | _linkableFields.push({ |
| | | value: item.field, |
| | | text: item.label + ' (表单)' |
| | | }) |
| | | _linksupFields.push({ |
| | | value: item.field, |
| | | text: item.label |
| | | }) |
| | | } |
| | | }) |
| | | if (index !== null) { |
| | | if (index === 0) { |
| | | standardform = config.fields[index + 1] || null |
| | | } else { |
| | | standardform = config.fields[index - 1] || null |
| | | } |
| | | } |
| | | |
| | | componentConfig.columns.forEach(col => { |
| | | if (col.field && !uniq.has(col.field)) { |
| | | uniq.set(col.field, true) |
| | | |
| | | _linkableFields.push({ |
| | | value: col.field, |
| | | text: col.label + ' (显示列)' |
| | | }) |
| | | } |
| | | }) |
| | | |
| | | if (card.linkSubField && card.linkSubField.length > 0) { |
| | | let fields = _inputfields.map(item => item.field) |
| | | card.linkSubField = card.linkSubField.filter(item => fields.includes(item)) |
| | | } |
| | | |
| | | if (!card.span && standardform && standardform.span) { |
| | | card.span = standardform.span |
| | | card.labelwidth = standardform.labelwidth |
| | | } |
| | | |
| | | this.setState({ |
| | | standardform, |
| | | visible: true, |
| | | card: card, |
| | | formlist: getModalForm(card, _inputfields, _tabfields, _linkableFields, _linksupFields, !!this.props.editTab) |
| | | }) |
| | | } |
| | | |
| | | /** |
| | | * @description 编辑后提交 |
| | | * 1、获取编辑后的表单信息 |
| | | * 2、去除可能存在的示例表单 |
| | | * 3、通过loading刷新 |
| | | */ |
| | | handleSubmit = () => { |
| | | 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) { |
| | | return res |
| | | } else { |
| | | return item |
| | | } |
| | | }) |
| | | |
| | | if (fieldrepet) { |
| | | notification.warning({ |
| | | top: 92, |
| | | message: '字段已存在!', |
| | | 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)) { |
| | | this.setState({ |
| | | sqlVerifing: true |
| | | }) |
| | | |
| | | let param = { |
| | | func: 's_debug_sql', |
| | | exec_type: 'y', |
| | | LText: res.dataSource |
| | | } |
| | | |
| | | param.LText = param.LText.replace(/@\$|\$@/ig, '') |
| | | |
| | | param.LText = Utils.formatOptions(param.LText) |
| | | param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss') |
| | | param.secretkey = Utils.encrypt('', param.timestamp) |
| | | |
| | | if (window.GLOB.mainSystemApi && res.database === 'sso') { |
| | | param.rduri = window.GLOB.mainSystemApi |
| | | } |
| | | |
| | | Api.getLocalConfig(param).then(result => { |
| | | if (result.status) { |
| | | this.setState({ |
| | | sqlVerifing: false, |
| | | config: _config, |
| | | card: null, |
| | | visible: false |
| | | }) |
| | | } else { |
| | | this.setState({sqlVerifing: false}) |
| | | |
| | | Modal.error({ |
| | | title: result.message |
| | | }) |
| | | } |
| | | }) |
| | | } else { |
| | | this.setState({ |
| | | config: _config, |
| | | card: null, |
| | | visible: false |
| | | }) |
| | | } |
| | | }) |
| | | } |
| | | |
| | | /** |
| | | * @description 表单删除并刷新 |
| | | */ |
| | | closeForm = (card) => { |
| | | let _this = this |
| | | |
| | | confirm({ |
| | | content: `确定删除${card.label ? `<<${card.label}>>` : ''}吗?`, |
| | | onOk() { |
| | | let _config = fromJS(_this.state.config).toJS() |
| | | _config.fields = _config.fields.filter(item => !(item.uuid === card.uuid)) |
| | | |
| | | _this.setState({ |
| | | config: _config, |
| | | }) |
| | | }, |
| | | onCancel() {} |
| | | }) |
| | | } |
| | | |
| | | submitConfig = () => { |
| | | const { config } = this.state |
| | | |
| | | this.setState({originConfig: fromJS(config).toJS(), closeVisible: false}) |
| | | this.props.handleSave(config) |
| | | notification.success({ |
| | | top: 92, |
| | | message: '保存成功。', |
| | | duration: 2 |
| | | }) |
| | | } |
| | | |
| | | cancelConfig = () => { |
| | | const { config, originConfig } = this.state |
| | | |
| | | if (!is(fromJS(config), fromJS(originConfig))) { |
| | | this.setState({ |
| | | closeVisible: true |
| | | }) |
| | | } else { |
| | | this.props.handleBack() |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * @description 全局设置模态框 |
| | | */ |
| | | changeSetting = () => { |
| | | this.setState({ |
| | | settingVisible: true |
| | | }) |
| | | } |
| | | |
| | | /** |
| | | * @description 保存全局设置 |
| | | */ |
| | | settingSave = () => { |
| | | const {config} = this.state |
| | | this.settingRef.handleConfirm().then(res => { |
| | | this.setState({ |
| | | config: {...config, setting: res}, |
| | | settingVisible: false |
| | | }) |
| | | }) |
| | | } |
| | | |
| | | editModalCancel = () => { |
| | | const { config, card } = this.state |
| | | |
| | | if (card.focus) { |
| | | let _fields = config.fields.filter(item => item.uuid !== card.uuid) |
| | | let _config = {...config, fields: _fields} |
| | | |
| | | this.setState({ |
| | | card: null, |
| | | config: _config, |
| | | visible: false |
| | | }) |
| | | } else { |
| | | this.setState({ |
| | | card: null, |
| | | visible: false |
| | | }) |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * @description 更新 |
| | | */ |
| | | updateConfig = (config) => { |
| | | this.setState({ |
| | | config |
| | | }) |
| | | } |
| | | |
| | | render () { |
| | | const { btn } = this.props |
| | | const { config, dict } = this.state |
| | | |
| | | return ( |
| | | <div className="mob-form-board"> |
| | | <DndProvider backend={HTML5Backend}> |
| | | <div className="tools"> |
| | | <Collapse accordion defaultActiveKey="1" bordered={false}> |
| | | <Panel header={dict['header.menu.form']} key="1"> |
| | | <div className="search-element"> |
| | | {SearchItems.map((item, index) => { |
| | | return (<SourceElement key={index} content={item}/>) |
| | | })} |
| | | </div> |
| | | <FieldsComponent |
| | | config={config} |
| | | type="form" |
| | | updatefield={this.updateConfig} |
| | | /> |
| | | </Panel> |
| | | </Collapse> |
| | | </div> |
| | | <div className="modal-control"> |
| | | <Button icon="setting" onClick={this.changeSetting}>设置</Button> |
| | | <Button type="primary" onClick={this.submitConfig}>保存</Button> |
| | | <Button onClick={this.cancelConfig}>返回</Button> |
| | | <PasteComponent type="menu" Tab={null} insert={this.insert} /> |
| | | <Switch checkedChildren={dict['model.switch.open']} unCheckedChildren={dict['model.switch.close']} defaultChecked={this.state.showField} onChange={(val) => this.setState({showField: val})} /> |
| | | </div> |
| | | <div className="setting"> |
| | | <div className="mob-shell" style={{width: window.GLOB.shellWidth, height: window.GLOB.shellHeight}}> |
| | | <div className="mob-shell-inner"> |
| | | <div className="am-navbar"> |
| | | <Icon type="close" /> |
| | | <div className="am-navbar-title">{btn.label}</div> |
| | | </div> |
| | | <DragElement |
| | | list={config.fields} |
| | | setting={config.setting} |
| | | showField={this.state.showField} |
| | | placeholder={this.state.dict['header.form.modal.placeholder']} |
| | | handleList={this.handleList} |
| | | handleForm={this.handleForm} |
| | | closeForm={this.closeForm} |
| | | /> |
| | | <Button className="modal-submit" type="primary">确定</Button> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </DndProvider> |
| | | <Modal |
| | | title={this.state.dict['model.edit']} |
| | | visible={this.state.visible} |
| | | width={850} |
| | | onCancel={this.editModalCancel} |
| | | onOk={this.handleSubmit} |
| | | confirmLoading={this.state.sqlVerifing} |
| | | destroyOnClose |
| | | > |
| | | <ModalForm |
| | | dict={this.state.dict} |
| | | card={this.state.card} |
| | | formlist={this.state.formlist} |
| | | inputSubmit={this.handleSubmit} |
| | | standardform={this.state.standardform} |
| | | wrappedComponentRef={(inst) => this.formRef = inst} |
| | | /> |
| | | </Modal> |
| | | <Modal |
| | | title={this.state.dict['model.edit']} |
| | | visible={this.state.settingVisible} |
| | | width={850} |
| | | maskClosable={false} |
| | | onOk={this.settingSave} |
| | | onCancel={() => { this.setState({ settingVisible: false }) }} |
| | | destroyOnClose |
| | | > |
| | | <SettingForm |
| | | config={config} |
| | | dict={this.state.dict} |
| | | isSubTab={!!this.props.editTab} |
| | | inputSubmit={this.settingSave} |
| | | 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> |
| | | ) |
| | | } |
| | | } |
| | | |
| | | export default ComModalConfig |
New file |
| | |
| | | .mob-form-board { |
| | | position: fixed; |
| | | z-index: 1070; |
| | | top: 48px; |
| | | left: 0px; |
| | | right: 0px; |
| | | bottom: 0px; |
| | | background: rgba(0, 0, 0, 1); |
| | | .tools { |
| | | position: absolute; |
| | | top: 0; |
| | | left: 0; |
| | | z-index: 1; |
| | | width: 235px; |
| | | background: #ffffff; |
| | | border-right: 1px solid #d9d9d9; |
| | | height: 100%; |
| | | overflow-y: auto; |
| | | padding-bottom: 30px; |
| | | .ant-collapse-borderless { |
| | | background-color: #ffffff; |
| | | } |
| | | .ant-collapse-item { |
| | | border: 0; |
| | | } |
| | | .ant-input-search { |
| | | margin-top: 10px; |
| | | } |
| | | .ant-collapse-item.ant-collapse-item-active { |
| | | border-bottom: 1px solid #d9d9d9; |
| | | } |
| | | .ant-collapse .ant-collapse-header { |
| | | padding: 11px 16px 10px 40px; |
| | | border-bottom: 1px solid #d9d9d9; |
| | | background: #1890ff; |
| | | color: #ffffff; |
| | | } |
| | | .ant-collapse-content-box { |
| | | .ant-form-item { |
| | | margin-bottom: 10px; |
| | | .ant-form-item-label { |
| | | text-align: left; |
| | | height: 25px; |
| | | line-height: 25px; |
| | | } |
| | | } |
| | | .ant-btn { |
| | | margin-bottom: 10px; |
| | | } |
| | | } |
| | | .search-element { |
| | | padding-top: 10px; |
| | | li { |
| | | padding: 0px 16px 10px; |
| | | div { |
| | | cursor: move; |
| | | } |
| | | } |
| | | } |
| | | .tables { |
| | | .ant-select-selection-selected-value { |
| | | opacity: 0.4!important; |
| | | } |
| | | } |
| | | .ant-list { |
| | | margin-top: 20px; |
| | | .ant-list-item { |
| | | display: -webkit-box; |
| | | padding-right: 20px; |
| | | position: relative; |
| | | padding-left: 5px; |
| | | overflow: hidden; |
| | | text-overflow: ellipsis; |
| | | -webkit-line-clamp: 2; |
| | | -webkit-box-orient: vertical; |
| | | width: 100%; |
| | | .anticon { |
| | | position: absolute; |
| | | top: 0px; |
| | | right: 0px; |
| | | padding: 3px 3px 10px 10px; |
| | | cursor: pointer; |
| | | } |
| | | .bottom-mask { |
| | | position: absolute; |
| | | width: 100%; |
| | | height: 8px; |
| | | bottom: 0; |
| | | left: 0; |
| | | background: #ffffff; |
| | | border-radius: 8px; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | .tools::-webkit-scrollbar { |
| | | width: 4px; |
| | | } |
| | | .tools::-webkit-scrollbar-thumb { |
| | | border-radius: 5px; |
| | | box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.08); |
| | | background: rgba(0, 0, 0, 0.08); |
| | | } |
| | | .tools::-webkit-scrollbar-track { |
| | | box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.05); |
| | | border-radius: 3px; |
| | | border: 1px solid rgba(0, 0, 0, 0.07); |
| | | background: rgba(0, 0, 0, 0); |
| | | } |
| | | .modal-control { |
| | | position: absolute; |
| | | right: 0; |
| | | top: 0; |
| | | width: 120px; |
| | | height: 100vh; |
| | | padding: 20px 10px; |
| | | background: #ffffff; |
| | | z-index: 10; |
| | | transition: right 0.3s; |
| | | |
| | | div:not(.draw), button:not(.ant-switch) { |
| | | display: block!important; |
| | | margin-bottom: 15px; |
| | | width: 100%; |
| | | } |
| | | .ant-switch.big { |
| | | min-width: 60px; |
| | | height: 24px; |
| | | line-height: 24px; |
| | | margin-bottom: 15px; |
| | | .ant-switch-inner { |
| | | font-size: 14px; |
| | | } |
| | | } |
| | | .ant-switch.big:after { |
| | | width: 22px; |
| | | height: 22px; |
| | | } |
| | | } |
| | | .setting { |
| | | position: relative; |
| | | width: 100vw; |
| | | height: 100%; |
| | | background: #959595; |
| | | |
| | | .mob-shell { |
| | | margin: 0 auto; |
| | | background: #000000; |
| | | background-size: 100% 100%; |
| | | padding: 25px 13px 40px; |
| | | border-radius: 30px; |
| | | |
| | | .am-navbar { |
| | | height: 45px; |
| | | line-height: 45px; |
| | | position: relative; |
| | | border-bottom: 1px solid #f0f0f0; |
| | | margin-bottom: 10px; |
| | | .anticon-close { |
| | | position: absolute; |
| | | line-height: 45px; |
| | | font-size: 18px; |
| | | left: 10px; |
| | | } |
| | | .am-navbar-title { |
| | | font-size: 16px; |
| | | text-align: center; |
| | | } |
| | | } |
| | | .modal-submit { |
| | | width: 100%; |
| | | border-radius: 0; |
| | | opacity: 0.5; |
| | | cursor: default; |
| | | font-size: 18px; |
| | | height: 40px; |
| | | } |
| | | |
| | | .modal-fields-row { |
| | | min-height: calc(100% - 95px); |
| | | } |
| | | |
| | | .modal-form { |
| | | padding: 0px 24px; |
| | | min-height: 87px; |
| | | .group-title { |
| | | position: relative; |
| | | min-height: 22px; |
| | | margin-bottom: 10px; |
| | | padding-top: 10px; |
| | | border-bottom: 1px solid #e8e8e8; |
| | | |
| | | span { |
| | | padding: 0 5px 5px; |
| | | } |
| | | } |
| | | > .ant-row { |
| | | min-height: 120px; |
| | | } |
| | | .ant-row .ant-col-6 { |
| | | padding: 0 12px!important; |
| | | } |
| | | .ant-row.ant-form-item .ant-col { |
| | | padding: 0; |
| | | } |
| | | .textarea2, .textarea4 { |
| | | padding-left: 7px; |
| | | } |
| | | .page-card { |
| | | position: relative; |
| | | background: #ffffff; |
| | | border-radius: 2px; |
| | | margin-bottom: 15px; |
| | | .ant-form-item { |
| | | cursor: move; |
| | | display: flex; |
| | | margin-bottom: 0px; |
| | | .ant-form-item-label { |
| | | overflow: visible; |
| | | position: relative; |
| | | height: 40px; |
| | | label { |
| | | width: 100%; |
| | | cursor: move; |
| | | overflow: hidden; |
| | | display: inline-block; |
| | | text-overflow: ellipsis; |
| | | white-space: nowrap; |
| | | } |
| | | } |
| | | .ant-form-item-control-wrapper { |
| | | position: relative; |
| | | .ant-select { |
| | | width: 100%; |
| | | margin-top: 4px; |
| | | } |
| | | .ant-calendar-picker { |
| | | width: 100%; |
| | | margin-top: 4px; |
| | | } |
| | | .ant-input-number { |
| | | width: 100%; |
| | | margin-top: 4px; |
| | | } |
| | | .normal-braft-editor { |
| | | border: 1px solid #d9d9d9; |
| | | border-radius: 4px; |
| | | } |
| | | } |
| | | .ant-form-item-control-wrapper::after { |
| | | content: ''; |
| | | position: absolute; |
| | | top: 0; |
| | | left: 0; |
| | | right: 0; |
| | | bottom: 0; |
| | | opacity: 0; |
| | | z-index: 1; |
| | | } |
| | | .ant-col-cuslabel { |
| | | width: 10.5%; |
| | | } |
| | | .ant-col-cuswrap { |
| | | width: 89.5%; |
| | | } |
| | | } |
| | | } |
| | | .ant-calendar-picker { |
| | | min-width: 100px!important; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | .setting { |
| | | overflow-y: auto; |
| | | } |
| | | .setting::-webkit-scrollbar { |
| | | width: 7px; |
| | | } |
| | | .setting::-webkit-scrollbar-thumb { |
| | | border-radius: 5px; |
| | | box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.13); |
| | | background: rgba(0, 0, 0, 0.13); |
| | | } |
| | | .setting::-webkit-scrollbar-track { |
| | | box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.05); |
| | | border-radius: 3px; |
| | | border: 1px solid rgba(0, 0, 0, 0.07); |
| | | background: rgba(0, 0, 0, 0); |
| | | } |
| | | } |
| | | |
| | | |
| | | .modal-fields { |
| | | .ant-modal { |
| | | top: 50px; |
| | | padding-bottom: 5px; |
| | | .ant-modal-body { |
| | | max-height: calc(100vh - 190px); |
| | | overflow-y: auto; |
| | | .ant-empty { |
| | | margin: 15vh 8px; |
| | | } |
| | | } |
| | | .ant-modal-body::-webkit-scrollbar { |
| | | width: 7px; |
| | | } |
| | | .ant-modal-body::-webkit-scrollbar-thumb { |
| | | border-radius: 5px; |
| | | box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.13); |
| | | background: rgba(0, 0, 0, 0.13); |
| | | } |
| | | .ant-modal-body::-webkit-scrollbar-track { |
| | | box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.05); |
| | | border-radius: 3px; |
| | | border: 1px solid rgba(0, 0, 0, 0.07); |
| | | background: rgba(0, 0, 0, 0); |
| | | } |
| | | } |
| | | } |
New file |
| | |
| | | import React, {Component} from 'react' |
| | | import PropTypes from 'prop-types' |
| | | import { Button, Modal, notification } from 'antd' |
| | | |
| | | import asyncComponent from '@/utils/asyncComponent' |
| | | import './index.scss' |
| | | |
| | | const PasteForm = asyncComponent(() => import('@/templates/zshare/pasteform')) |
| | | |
| | | class PasteController extends Component { |
| | | static propTpyes = { |
| | | config: PropTypes.object, // 组件配置 |
| | | updateConfig: PropTypes.func |
| | | } |
| | | |
| | | state = { |
| | | visible: false |
| | | } |
| | | |
| | | pasteSubmit = () => { |
| | | const { config } = this.props |
| | | this.pasteFormRef.handleConfirm().then(res => { |
| | | if (res.copyType !== 'form') { |
| | | notification.warning({ top: 92, message: '配置信息格式错误!', duration: 5 }) |
| | | return |
| | | } |
| | | |
| | | let keys = config.fields.map(item => item.field ? item.field.toLowerCase() : '$emp_ty$') |
| | | |
| | | if (['multiselect', 'color', 'brafteditor'].includes(res.type)) { |
| | | res.type = 'text' |
| | | } |
| | | |
| | | if (res.field && keys.includes(res.field.toLowerCase())) { |
| | | notification.warning({ |
| | | top: 92, |
| | | message: '搜索字段已存在!', |
| | | duration: 5 |
| | | }) |
| | | return |
| | | } |
| | | |
| | | this.props.updateConfig(config) |
| | | this.setState({visible: false}) |
| | | |
| | | notification.success({ |
| | | top: 92, |
| | | message: '粘贴成功!', |
| | | duration: 2 |
| | | }) |
| | | }) |
| | | } |
| | | |
| | | render() { |
| | | const { visible } = this.state |
| | | |
| | | return ( |
| | | <div style={{display: 'inline-block'}}> |
| | | <Button icon="snippets" style={{color: 'purple'}} onClick={() => {this.setState({visible: true})}} >粘贴</Button> |
| | | <Modal |
| | | title="粘贴" |
| | | visible={visible} |
| | | width={600} |
| | | maskClosable={false} |
| | | onOk={this.pasteSubmit} |
| | | onCancel={() => {this.setState({visible: false})}} |
| | | destroyOnClose |
| | | > |
| | | <PasteForm wrappedComponentRef={(inst) => this.pasteFormRef = inst} inputSubmit={this.pasteSubmit}/> |
| | | </Modal> |
| | | </div> |
| | | ) |
| | | } |
| | | } |
| | | |
| | | export default PasteController |
New file |
| | |
| | | import zhCN from '@/locales/zh-CN/model.js' |
| | | import enUS from '@/locales/en-US/model.js' |
| | | |
| | | const CommonDict = sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS |
| | | |
| | | export const SearchItems = [ |
| | | { |
| | | type: 'form', |
| | | label: CommonDict['model.form.text'], |
| | | subType: 'text', |
| | | url: '' |
| | | }, |
| | | { |
| | | type: 'form', |
| | | label: CommonDict['model.form.number'], |
| | | subType: 'number', |
| | | url: '' |
| | | }, |
| | | { |
| | | type: 'form', |
| | | label: CommonDict['model.form.select'], |
| | | subType: 'select', |
| | | url: '' |
| | | }, |
| | | { |
| | | type: 'form', |
| | | label: CommonDict['model.form.link'], |
| | | subType: 'link', |
| | | url: '' |
| | | }, |
| | | { |
| | | type: 'form', |
| | | label: '开关', |
| | | subType: 'switch', |
| | | url: '' |
| | | }, |
| | | { |
| | | type: 'form', |
| | | label: '多选框', |
| | | subType: 'checkbox', |
| | | url: '' |
| | | }, |
| | | { |
| | | type: 'form', |
| | | label: '单选框', |
| | | subType: 'radio', |
| | | url: '' |
| | | }, |
| | | { |
| | | type: 'form', |
| | | label: '选项卡', |
| | | subType: 'checkcard', |
| | | url: '' |
| | | }, |
| | | { |
| | | type: 'form', |
| | | label: CommonDict['header.form.fileupload'], |
| | | subType: 'fileupload', |
| | | url: '' |
| | | }, |
| | | { |
| | | type: 'form', |
| | | label: CommonDict['model.form.dateday'], |
| | | subType: 'date', |
| | | url: '' |
| | | }, |
| | | { |
| | | type: 'form', |
| | | label: CommonDict['model.form.datemonth'], |
| | | subType: 'datemonth', |
| | | url: '' |
| | | }, |
| | | { |
| | | type: 'form', |
| | | label: CommonDict['model.form.datetime'], |
| | | subType: 'datetime', |
| | | url: '' |
| | | }, |
| | | { |
| | | type: 'form', |
| | | label: CommonDict['model.form.textarea'], |
| | | subType: 'textarea', |
| | | url: '' |
| | | }, |
| | | { |
| | | type: 'form', |
| | | label: CommonDict['header.form.funcvar'], |
| | | subType: 'funcvar', |
| | | url: '' |
| | | }, |
| | | { |
| | | type: 'form', |
| | | label: '提示', |
| | | subType: 'hint', |
| | | url: '' |
| | | }, |
| | | { |
| | | type: 'form', |
| | | label: '分割线', |
| | | subType: 'split', |
| | | url: '' |
| | | } |
| | | ] |
| | | |
| | |
| | | } else { |
| | | _chart.color(_typefield) |
| | | } |
| | | if (plot.label === 'true') { |
| | | if (plot.label !== 'false') { |
| | | _chart.label(_valfield, (value) => { |
| | | if (plot.show === 'percent') { |
| | | value = value + '%' |
| | |
| | | } else { |
| | | _chart.color('key') |
| | | } |
| | | if (plot.label === 'true') { |
| | | if (plot.label !== 'false') { |
| | | _chart.label('value*key', (value, key) => { |
| | | if (plot.show === 'percent') { |
| | | value = value + '%' |
| | |
| | | } else { |
| | | _chart.color('key') |
| | | } |
| | | if (plot.label === 'true') { |
| | | if (plot.label !== 'false') { |
| | | _chart.label('value*key', (value, key) => { |
| | | if (plot.show === 'percent') { |
| | | value = value + '%' |
| | |
| | | if (plot.barSize) { |
| | | _chart.size(plot.barSize || 35) |
| | | } |
| | | if (item.label === 'true') { |
| | | if (item.label !== 'false') { |
| | | _chart.label(item.name, (value) => { |
| | | if (plot.show === 'percent') { |
| | | value = value + '%' |
| | |
| | | } else { |
| | | _chart.color(_typefield) |
| | | } |
| | | if (plot.label === 'true') { |
| | | if (plot.label !== 'false') { |
| | | _chart.label(`${_valfield}*${_typefield}`, (value, key) => { |
| | | if (plot.show === 'percent') { |
| | | value = value + '%' |
| | |
| | | } else { |
| | | _chart.color(_typefield) |
| | | } |
| | | if (plot.label === 'true') { |
| | | if (plot.label !== 'false') { |
| | | _chart.label(`${_valfield}*${_typefield}`, (value, key) => { |
| | | if (plot.show === 'percent') { |
| | | value = value + '%' |
| | |
| | | if (btn.search === 'true' && viewParam.search && viewParam.search.length > 0) { |
| | | let valid = false |
| | | viewParam.search.forEach(item => { |
| | | if (Array.isArray(item.value) && item.value.length > 0) { |
| | | valid = true |
| | | } else if (item.value || item.value === 0) { |
| | | if (item.value || item.value === 0) { |
| | | valid = true |
| | | } |
| | | }) |
| | |
| | | import React, {Component} from 'react' |
| | | import PropTypes from 'prop-types' |
| | | import { Form, Row, Col, Input, Radio, InputNumber, Select } from 'antd' |
| | | import { Form, Row, Col, Input, Radio, InputNumber, Select, Tooltip, Icon } from 'antd' |
| | | import { formRule } from '@/utils/option.js' |
| | | import './index.scss' |
| | | |
| | |
| | | |
| | | UNSAFE_componentWillMount () { |
| | | const { config } = this.props |
| | | const { appType, display } = this.state |
| | | let fields = [] |
| | | |
| | | config.fields.forEach(f => { |
| | |
| | | } |
| | | }) |
| | | |
| | | let _display = display |
| | | if (appType === 'mob' && display !== 'prompt' && display !== 'drawer') { |
| | | _display = 'drawer' |
| | | } |
| | | |
| | | this.setState({ |
| | | fields: fields |
| | | fields: fields, |
| | | display: _display |
| | | }) |
| | | } |
| | | |
| | |
| | | })(<Input placeholder="" autoComplete="off" onPressEnter={this.handleSubmit} />)} |
| | | </Form.Item> |
| | | </Col> |
| | | <Col span={12}> |
| | | {appType !== 'mob' ? <Col span={12}> |
| | | <Form.Item label="宽度(%)"> |
| | | {getFieldDecorator('width', { |
| | | initialValue: config.setting.width |
| | | })(<InputNumber min={10} max={90} precision={0} onPressEnter={this.handleSubmit}/>)} |
| | | </Form.Item> |
| | | </Col> |
| | | </Col> : null} |
| | | {appType === 'mob' ? <Col span={12}> |
| | | <Form.Item label={ |
| | | <Tooltip placement="topLeft" title="宽度小于100时为百分率,大于100时为绝对值。"> |
| | | <Icon type="question-circle" /> |
| | | 宽度 |
| | | </Tooltip> |
| | | }> |
| | | {getFieldDecorator('width', { |
| | | initialValue: config.setting.width |
| | | })(<InputNumber min={10} max={2000} precision={0} onPressEnter={this.handleSubmit}/>)} |
| | | </Form.Item> |
| | | </Col> : null} |
| | | <Col span={12}> |
| | | <Form.Item label="焦点"> |
| | | {getFieldDecorator('focus', { |
| | |
| | | )} |
| | | </Form.Item> |
| | | </Col> |
| | | <Col span={12}> |
| | | {appType !== 'mob' ? <Col span={12}> |
| | | <Form.Item label="表单排列"> |
| | | {getFieldDecorator('align', { |
| | | initialValue: config.setting.align || 'left_right' |
| | |
| | | </Radio.Group> |
| | | )} |
| | | </Form.Item> |
| | | </Col> |
| | | </Col> : null} |
| | | <Col span={12}> |
| | | <Form.Item label="完成后"> |
| | | {getFieldDecorator('finish', { |
| | |
| | | <Col span={12}> |
| | | <Form.Item label="显示方式"> |
| | | {getFieldDecorator('display', { |
| | | initialValue: config.setting.display || 'modal' |
| | | initialValue: display || 'modal' |
| | | })( |
| | | <Radio.Group style={{whiteSpace: 'nowrap'}} onChange={(e) => this.setState({display: e.target.value})}> |
| | | <Radio value="modal">模态框</Radio> |
| | | {appType !== 'mob' ? <Radio value="modal">模态框</Radio> : null} |
| | | <Radio value="prompt">是否框</Radio> |
| | | <Radio value="drawer">抽屉</Radio> |
| | | </Radio.Group> |
| | | )} |
| | | </Form.Item> |
| | | </Col> |
| | | {!this.props.isSubTab && appType !== 'pc' && display === 'modal' ? <Col span={12}> |
| | | {!this.props.isSubTab && !appType && display === 'modal' ? <Col span={12}> |
| | | <Form.Item label="挂载对象"> |
| | | {getFieldDecorator('container', { |
| | | initialValue: config.setting.container || 'tab' |
| | |
| | | .ant-input-number { |
| | | width: 100%; |
| | | } |
| | | .anticon-question-circle { |
| | | color: #c49f47; |
| | | position: relative; |
| | | left: -3px; |
| | | } |
| | | } |
| | |
| | | label: '扫码', |
| | | initVal: card.scan || 'false', |
| | | options: [{ |
| | | value: 'true', |
| | | text: '启用' |
| | | }, { |
| | | value: 'false', |
| | | text: '不启用' |
| | | text: '禁用' |
| | | }, { |
| | | value: 'simple', |
| | | text: '单次扫码' |
| | | }, { |
| | | value: 'multi', |
| | | text: '连续扫码' |
| | | }], |
| | | forbid: appType !== 'mob' |
| | | }, |
| | |
| | | const StyleController = asyncComponent(() => import('@/menu/stylecontroller')) |
| | | const UrlFieldComponent = asyncComponent(() => import('@/menu/urlfieldcomponent')) |
| | | const PictureController = asyncComponent(() => import('@/menu/picturecontroller')) |
| | | const ModalController = asyncComponent(() => import('@/menu/modalconfig/controller')) |
| | | const ModalController = asyncComponent(() => import('@/mob/modalconfig/controller')) |
| | | const StyleCombController = asyncComponent(() => import('@/menu/stylecombcontroller')) |
| | | const StyleCombControlButton = asyncComponent(() => import('@/menu/stylecombcontrolbutton')) |
| | | const TableComponent = asyncComponent(() => import('@/templates/sharecomponent/tablecomponent')) |
| | |
| | | <div className="pc-setting-tools"> |
| | | <Collapse accordion activeKey={activeKey} bordered={false} onChange={(key) => this.setState({activeKey: key})}> |
| | | {/* 基本信息 */} |
| | | <Panel header={dict['mob.basemsg']} key="basedata"> |
| | | <Panel header={dict['mob.basemsg']} forceRender key="basedata"> |
| | | {/* 菜单信息 */} |
| | | {config ? <MenuForm |
| | | dict={dict} |