| | |
| | | </Col> |
| | | <Col span={24} className="sqlfield"> |
| | | <Form.Item label={'可用字段'}> |
| | | id, bid, loginuid, sessionuid, userid, username, fullname, login_city, appkey, time_id, orderBy, pageSize, pageIndex{usefulFields ? ', ' + usefulFields : ''} |
| | | id, bid, loginuid, sessionuid, userid, username, fullname, login_city, appkey, time_id, orderBy, pageSize, pageIndex{usefulFields ? ', ' + usefulFields : ''}{window.GLOB.urlFields ? ', ' + window.GLOB.urlFields.join(', ') : ''} |
| | | </Form.Item> |
| | | </Col> |
| | | <Col span={10} style={{width: '43%'}}> |
| | |
| | | inputType: 'input', |
| | | editable: true, |
| | | unique: true, |
| | | copy: true, |
| | | width: '28%' |
| | | }, |
| | | { |
| | |
| | | |
| | | const WrapComponent = asyncIconComponent(() => import('./wrapsetting')) |
| | | const MenuComponent = asyncIconComponent(() => import('./menusetting')) |
| | | const SettingComponent = asyncIconComponent(() => import('@/menu/datasource')) |
| | | |
| | | class NormalNavbar extends Component { |
| | | static propTpyes = { |
| | |
| | | uuid: card.uuid, |
| | | type: card.type, |
| | | floor: card.floor, |
| | | dataName: '', |
| | | format: 'object', // 组件属性 - 数据格式 |
| | | pageable: false, // 组件属性 - 是否可分页 |
| | | switchable: false, // 组件属性 - 数据是否可切换 |
| | | dataName: card.dataName || '', |
| | | width: card.width || 24, |
| | | name: card.name, |
| | | subtype: card.subtype, |
| | | wrap: { name: card.name, width: card.width || 1200 }, |
| | | style: { }, |
| | | setting: { interType: 'system' }, |
| | | wrap: { name: card.name, datatype: 'static', height: 50 }, |
| | | style: {borderTopColor: '#bcbcbc', borderTopWidth: '1px', paddingTop: '5px', fontSize: '13px' }, |
| | | menus: [], |
| | | columns: [], |
| | | scripts: [], |
| | | } |
| | | |
| | | if (card.config) { |
| | |
| | | |
| | | if (comIds[0] !== card.uuid) return |
| | | |
| | | let _card = {...card} |
| | | if (comIds.length === 1) { |
| | | _card = {...card, style} |
| | | } |
| | | let _card = {...card, style} |
| | | |
| | | this.setState({ |
| | | card: _card |
| | |
| | | changeStyle = () => { |
| | | const { card } = this.state |
| | | |
| | | MKEmitter.emit('changeStyle', [card.uuid], ['font', 'background', 'shadow'], card.style) |
| | | MKEmitter.emit('changeStyle', [card.uuid], ['font', 'background', 'border', 'padding'], card.style) |
| | | } |
| | | |
| | | clickComponent = (e) => { |
| | |
| | | changeMenu = (menu) => { |
| | | if (menu.property === 'link') { |
| | | window.open(menu.link) |
| | | return |
| | | } else { |
| | | MKEmitter.emit('changeEditMenu', { |
| | | fixed: menu.property === 'menu', |
| | | MenuID: menu.property === 'linkmenu' ? menu.linkMenuId : menu.MenuID, |
| | | copyMenuId: menu.property === 'menu' ? menu.copyMenuId : '', |
| | | MenuNo: menu.MenuNo, |
| | | MenuName: menu.name, |
| | | }) |
| | | } |
| | | MKEmitter.emit('changeEditMenu', { |
| | | fixed: menu.property === 'menu', |
| | | MenuID: menu.property === 'linkmenu' ? menu.linkMenuId : menu.MenuID, |
| | | copyMenuId: menu.property === 'menu' ? menu.copyMenuId : '', |
| | | MenuNo: menu.MenuNo, |
| | | MenuName: menu.name, |
| | | }) |
| | | } |
| | | |
| | | render() { |
| | |
| | | if (_style.shadow) { |
| | | _style.boxShadow = '0 0 4px ' + _style.shadow |
| | | } |
| | | _style.height = card.wrap.height |
| | | |
| | | return ( |
| | | <div className="normal-navbar-edit-box" style={_style} onClick={this.clickComponent} id={card.uuid}> |
| | |
| | | <WrapComponent config={card} updateConfig={this.updateComponent} /> |
| | | <Icon className="style" title="调整样式" onClick={this.changeStyle} type="font-colors" /> |
| | | <Icon className="close" title="删除组件" type="delete" onClick={() => this.props.deletecomponent(card.uuid)} /> |
| | | {card.wrap.datatype !== 'static' ? <SettingComponent config={card} updateConfig={this.updateComponent} /> : null} |
| | | {card.wrap.datatype === 'static' ? <Icon style={{color: '#eeeeee', cursor: 'not-allowed'}} type="setting"/> : null} |
| | | </div> |
| | | } trigger="hover"> |
| | | <Icon type="tool" /> |
| | |
| | | <div className="menu"> |
| | | {card.menus.map(menu => { |
| | | return ( |
| | | <div class="am-tab-bar-tab"> |
| | | <div class="am-tab-bar-tab-icon"> |
| | | <span class="am-badge am-tab-bar-tab-badge tab-badge"> |
| | | <Icon type="font-colors" /> |
| | | <sup class="am-badge-text">1</sup> |
| | | <div key={menu.MenuID} className="am-tab-bar-tab" onDoubleClick={() => this.changeMenu(menu)}> |
| | | {menu.icon ? <div className="am-tab-bar-tab-icon"> |
| | | <span className="am-badge am-tab-bar-tab-badge tab-badge"> |
| | | <Icon type={menu.icon} /> |
| | | {menu.tip ? <sup className="am-badge-text"></sup> : null} |
| | | </span> |
| | | </div> |
| | | <p class="am-tab-bar-tab-title">{menu.name}</p> |
| | | </div> : null} |
| | | <p className="am-tab-bar-tab-title">{menu.name}</p> |
| | | </div> |
| | | ) |
| | | })} |
| | |
| | | background-position: center center; |
| | | background-repeat: no-repeat; |
| | | background-size: cover; |
| | | min-height: 50px; |
| | | min-height: 30px; |
| | | z-index: 3; |
| | | |
| | | .menu { |
| | | display: block; |
| | | height: 100%; |
| | | display: flex; |
| | | font-size: inherit; |
| | | color: inherit; |
| | | .ant-menu { |
| | | background: transparent; |
| | | line-height: inherit; |
| | | font-size: inherit; |
| | | color: inherit; |
| | | border: 0; |
| | | .ant-menu-item:hover, .ant-menu-item-active { |
| | | color: unset; |
| | | .am-tab-bar-tab { |
| | | position: relative; |
| | | text-align: center; |
| | | flex: 1; |
| | | cursor: pointer; |
| | | .anticon { |
| | | font-size: 150%; |
| | | } |
| | | .ant-menu-item span { |
| | | display: inline-block; |
| | | .am-badge-text { |
| | | position: absolute; |
| | | top: -2px; |
| | | height: 8px; |
| | | width: 8px; |
| | | border-radius: 100%; |
| | | background: #ff5b05; |
| | | z-index: 1; |
| | | } |
| | | p { |
| | | margin-bottom: 0; |
| | | } |
| | | } |
| | | .ant-menu-horizontal > .ant-menu-item:hover, .ant-menu-horizontal > .ant-menu-item-active, .ant-menu-horizontal > .ant-menu-item-open, .ant-menu-horizontal > .ant-menu-item-selected { |
| | | color: unset; |
| | | } |
| | | } |
| | | .card-control { |
| | | position: absolute; |
| | | top: 0px; |
| | | left: 0px; |
| | | .anticon-tool { |
| | | right: auto; |
| | | left: 1px; |
| | | padding: 1px; |
| | | } |
| | | } |
| | | |
| | | .anticon-tool { |
| | | position: absolute; |
| | | z-index: 2; |
| | |
| | | .top-menu-popover { |
| | | padding-top: 0!important; |
| | | } |
| | | .normal-navbar-submenu { |
| | | .ant-menu-item-group { |
| | | float: left; |
| | | } |
| | | .ant-menu-item { |
| | | height: 32px; |
| | | line-height: 32px; |
| | | span { |
| | | display: inline-block; |
| | | width: 100%; |
| | | height: 100%; |
| | | padding: 0 16px 0 28px; |
| | | } |
| | | padding: 0; |
| | | } |
| | | .ant-menu .ant-menu-item-selected { |
| | | background-color: #ffffff; |
| | | } |
| | | } |
| | |
| | | > |
| | | <MenuTable |
| | | menus={config.menus} |
| | | cols={config.columns} |
| | | ref={(ref) => { this.mTable = ref }} |
| | | /> |
| | | </Modal> |
| | |
| | | import PropTypes from 'prop-types' |
| | | import { Form, Row, Col, Input, Radio, Tooltip, Icon, Select } from 'antd' |
| | | |
| | | import { minkeIconSystem } from '@/utils/option.js' |
| | | import './index.scss' |
| | | |
| | | const { TextArea } = Input |
| | | |
| | | class SettingForm extends Component { |
| | | static propTpyes = { |
| | | menu: PropTypes.object, // 卡片行信息 |
| | | menu: PropTypes.object, // 菜单信息 |
| | | cols: PropTypes.array, // 字段集 |
| | | inputSubmit: PropTypes.func // 回车事件 |
| | | } |
| | | |
| | |
| | | } |
| | | |
| | | render() { |
| | | const { menu } = this.props |
| | | const { menu, cols } = this.props |
| | | const { getFieldDecorator } = this.props.form |
| | | const { property, appMenus } = this.state |
| | | |
| | |
| | | return ( |
| | | <Form {...formItemLayout}> |
| | | <Row gutter={24}> |
| | | <Col span={22}> |
| | | <Col span={12}> |
| | | <Form.Item label="菜单名称"> |
| | | {getFieldDecorator('name', { |
| | | initialValue: menu.name, |
| | |
| | | })(<Input placeholder={''} autoComplete="off" onPressEnter={this.handleSubmit} />)} |
| | | </Form.Item> |
| | | </Col> |
| | | <Col span={22}> |
| | | <Col span={12}> |
| | | <Form.Item label="菜单参数"> |
| | | {getFieldDecorator('MenuNo', { |
| | | initialValue: menu.MenuNo || '', |
| | |
| | | })(<Input placeholder={''} autoComplete="off" onPressEnter={this.handleSubmit} />)} |
| | | </Form.Item> |
| | | </Col> |
| | | <Col span={22}> |
| | | <Col span={12}> |
| | | <Form.Item label="图标"> |
| | | {getFieldDecorator('icon', { |
| | | initialValue: menu.icon || '' |
| | | })( |
| | | <Select> |
| | | {appMenus.map(item => (<Select.Option key={item.MenuID} value={item.MenuID}>{item.MenuName}</Select.Option>))} |
| | | <Select showSearch allowClear> |
| | | {minkeIconSystem.normal.map(icon => <Select.Option key={icon} value={icon}><Icon type={icon} /></Select.Option>)} |
| | | {minkeIconSystem.trademark.map(icon => <Select.Option key={icon} value={icon}><Icon type={icon} /></Select.Option>)} |
| | | {minkeIconSystem.data.map(icon => <Select.Option key={icon} value={icon}><Icon type={icon} /></Select.Option>)} |
| | | {minkeIconSystem.edit.map(icon => <Select.Option key={icon} value={icon}><Icon type={icon} /></Select.Option>)} |
| | | {minkeIconSystem.hint.map(icon => <Select.Option key={icon} value={icon}><Icon type={icon} /></Select.Option>)} |
| | | {minkeIconSystem.direction.map(icon => <Select.Option key={icon} value={icon}><Icon type={icon} /></Select.Option>)} |
| | | </Select> |
| | | )} |
| | | </Form.Item> |
| | | </Col> |
| | | <Col span={22}> |
| | | <Col span={12}> |
| | | <Form.Item label={ |
| | | <Tooltip placement="topLeft" title="绑定提示字段后,会在菜单右上角显示提示信息。注:在添加图标时有效。"> |
| | | <Icon type="question-circle" style={{color: '#c49f47', marginRight: '3px'}}/> |
| | | 提示 |
| | | </Tooltip> |
| | | }> |
| | | {getFieldDecorator('tip', { |
| | | initialValue: menu.tip || '' |
| | | })( |
| | | <Select allowClear> |
| | | {cols.map(item => <Select.Option key={item.uuid} value={item.field}>{item.label}</Select.Option>)} |
| | | </Select> |
| | | )} |
| | | </Form.Item> |
| | | </Col> |
| | | <Col span={12}> |
| | | <Form.Item label="菜单属性"> |
| | | {getFieldDecorator('property', { |
| | | initialValue: menu.property || 'menu' |
| | | })( |
| | | <Radio.Group onChange={this.changeProperty}> |
| | | <Radio.Group onChange={this.changeProperty} style={{whiteSpace: 'nowrap'}}> |
| | | <Radio value="menu">菜单</Radio> |
| | | <Radio value="link">链接</Radio> |
| | | <Radio value="linkmenu">关联菜单</Radio> |
| | |
| | | )} |
| | | </Form.Item> |
| | | </Col> |
| | | <Col span={22}> |
| | | <Col span={12}> |
| | | <Form.Item label="隐藏"> |
| | | {getFieldDecorator('hidden', { |
| | | initialValue: menu.hidden || 'false' |
| | |
| | | )} |
| | | </Form.Item> |
| | | </Col> |
| | | {property === 'link' ? <Col span={22}> |
| | | {property === 'link' ? <Col span={12}> |
| | | <Form.Item label="链接地址"> |
| | | {getFieldDecorator('link', { |
| | | initialValue: menu.link || '', |
| | |
| | | })(<TextArea rows={2} />)} |
| | | </Form.Item> |
| | | </Col> : null} |
| | | {property === 'linkmenu' ? <Col span={22}> |
| | | {property === 'linkmenu' ? <Col span={12}> |
| | | <Form.Item label={ |
| | | <Tooltip placement="topLeft" title="关联当前app中已有的菜单。"> |
| | | <Icon type="question-circle" style={{color: '#c49f47', marginRight: '3px'}}/> |
| | |
| | | )} |
| | | </Form.Item> |
| | | </Col> : null} |
| | | {property === 'menu' ? <Col span={22}> |
| | | {property === 'menu' ? <Col span={12}> |
| | | <Form.Item label={ |
| | | <Tooltip placement="topLeft" title="复制菜单仅在当前菜单不存在时有效。"> |
| | | <Icon type="question-circle" style={{color: '#c49f47', marginRight: '3px'}}/> |
| | |
| | | |
| | | class MenuTable extends Component { |
| | | static propTpyes = { |
| | | menus: PropTypes.object, // 卡片行信息 |
| | | menus: PropTypes.array, // 卡片行信息 |
| | | cols: PropTypes.array, // 字段集 |
| | | } |
| | | |
| | | state = { |
| | |
| | | const trans = {menu: '菜单', link: '链接', linkmenu: '关联菜单'} |
| | | |
| | | return trans[text] |
| | | }}, |
| | | { title: '图标', dataIndex: 'icon', key: 'icon', render: (text, record) => { |
| | | return text ? <Icon type={text} /> : '' |
| | | }}, |
| | | { title: '是否隐藏', dataIndex: 'hidden', key: 'hidden', render: (text, record) => { |
| | | const trans = {'true': '是', 'false': '否'} |
| | |
| | | } |
| | | |
| | | render() { |
| | | const { cols } = this.props |
| | | const { columns, data, visible, editMenu } = this.state |
| | | |
| | | return ( |
| | |
| | | <Modal |
| | | title="编辑" |
| | | visible={visible} |
| | | width={600} |
| | | width={750} |
| | | maskClosable={false} |
| | | onOk={this.menuSubmit} |
| | | onCancel={() => { this.setState({ visible: false }) }} |
| | |
| | | > |
| | | <MenuForm |
| | | menu={editMenu} |
| | | cols={cols} |
| | | inputSubmit={this.menuSubmit} |
| | | wrappedComponentRef={(inst) => this.menuRef = inst} |
| | | /> |
| | |
| | | } |
| | | |
| | | render () { |
| | | const { config } = this.props |
| | | const { visible, dict, wrap } = this.state |
| | | |
| | | return ( |
| | |
| | | <Icon type="edit" title="编辑" onClick={() => this.editDataSource()} /> |
| | | <Modal |
| | | wrapClassName="popview-modal" |
| | | title={config.type === 'table' ? '表格设置' : '卡片设置'} |
| | | title="菜单栏设置" |
| | | visible={visible} |
| | | width={800} |
| | | maskClosable={false} |
| | |
| | | <SettingForm |
| | | dict={dict} |
| | | wrap={wrap} |
| | | config={config} |
| | | inputSubmit={this.verifySubmit} |
| | | wrappedComponentRef={(inst) => this.verifyRef = inst} |
| | | /> |
| | |
| | | import React, {Component} from 'react' |
| | | import PropTypes from 'prop-types' |
| | | import { Form, Row, Col, Input, InputNumber } from 'antd' |
| | | import { Form, Row, Col, Input, InputNumber, Tooltip, Icon, Radio } from 'antd' |
| | | |
| | | import './index.scss' |
| | | |
| | | class SettingForm extends Component { |
| | | static propTpyes = { |
| | | dict: PropTypes.object, // 字典项 |
| | | config: PropTypes.object, // 卡片行信息 |
| | | wrap: PropTypes.object, // 数据源配置 |
| | | inputSubmit: PropTypes.func // 回车事件 |
| | | } |
| | |
| | | </Form.Item> |
| | | </Col> |
| | | <Col span={12}> |
| | | <Form.Item label={ |
| | | <Tooltip placement="topLeft" title="选择静态值,无需配置数据源。"> |
| | | <Icon type="question-circle" /> |
| | | 数据来源 |
| | | </Tooltip> |
| | | }> |
| | | {getFieldDecorator('datatype', { |
| | | initialValue: wrap.datatype || 'static' |
| | | })( |
| | | <Radio.Group> |
| | | <Radio value="dynamic">动态</Radio> |
| | | <Radio value="static">静态</Radio> |
| | | </Radio.Group> |
| | | )} |
| | | </Form.Item> |
| | | </Col> |
| | | <Col span={12}> |
| | | <Form.Item label="高度"> |
| | | {getFieldDecorator('height', { |
| | | initialValue: wrap.height || 50, |
| | |
| | | message: this.props.dict['form.required.input'] + '高度!' |
| | | } |
| | | ] |
| | | })(<InputNumber min={50} max={200} precision={0} onPressEnter={this.handleSubmit} />)} |
| | | })(<InputNumber min={30} max={200} precision={0} onPressEnter={this.handleSubmit} />)} |
| | | </Form.Item> |
| | | </Col> |
| | | </Row> |
New file |
| | |
| | | import React, {Component} from 'react' |
| | | import PropTypes from 'prop-types' |
| | | import { is, fromJS } from 'immutable' |
| | | import { Icon, Popover } from 'antd' |
| | | |
| | | import asyncIconComponent from '@/utils/asyncIconComponent' |
| | | |
| | | import MKEmitter from '@/utils/events.js' |
| | | import zhCN from '@/locales/zh-CN/model.js' |
| | | import enUS from '@/locales/en-US/model.js' |
| | | import './index.scss' |
| | | |
| | | const WrapComponent = asyncIconComponent(() => import('./wrapsetting')) |
| | | |
| | | class NormalNavbar extends Component { |
| | | static propTpyes = { |
| | | card: PropTypes.object, |
| | | deletecomponent: PropTypes.func, |
| | | updateConfig: PropTypes.func, |
| | | } |
| | | |
| | | state = { |
| | | dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS, |
| | | card: null, |
| | | back: false |
| | | } |
| | | |
| | | UNSAFE_componentWillMount () { |
| | | const { card } = this.props |
| | | |
| | | if (card.isNew) { |
| | | let _card = { |
| | | uuid: card.uuid, |
| | | type: card.type, |
| | | floor: card.floor, |
| | | width: card.width || 24, |
| | | subtype: card.subtype, |
| | | wrap: { height: 50, title: 'NavBar' }, |
| | | style: {borderBottomColor: '#bcbcbc', borderBottomWidth: '1px', paddingLeft: '10px', paddingRight: '10px', lineHeight: '2.8', fontSize: '18px' }, |
| | | } |
| | | |
| | | if (card.config) { |
| | | let config = fromJS(card.config).toJS() |
| | | |
| | | _card.wrap = config.wrap |
| | | _card.style = config.style |
| | | } |
| | | |
| | | this.setState({ |
| | | card: _card |
| | | }) |
| | | this.props.updateConfig(_card) |
| | | } else { |
| | | this.setState({ |
| | | card: fromJS(card).toJS() |
| | | }) |
| | | } |
| | | } |
| | | |
| | | componentDidMount () { |
| | | MKEmitter.addListener('submitStyle', this.getStyle) |
| | | } |
| | | |
| | | shouldComponentUpdate (nextProps, nextState) { |
| | | return !is(fromJS(this.state), fromJS(nextState)) |
| | | } |
| | | |
| | | /** |
| | | * @description 组件销毁,清除state更新,清除快捷键设置 |
| | | */ |
| | | componentWillUnmount () { |
| | | this.setState = () => { |
| | | return |
| | | } |
| | | MKEmitter.removeListener('submitStyle', this.getStyle) |
| | | } |
| | | |
| | | /** |
| | | * @description 卡片行外层信息更新(数据源,样式等) |
| | | */ |
| | | updateComponent = (component) => { |
| | | this.setState({ |
| | | card: component |
| | | }) |
| | | |
| | | component.width = component.wrap.width |
| | | component.name = component.wrap.name |
| | | |
| | | this.props.updateConfig(component) |
| | | } |
| | | |
| | | getStyle = (comIds, style) => { |
| | | const { card } = this.state |
| | | |
| | | if (comIds[0] !== card.uuid) return |
| | | |
| | | let _card = {...card, style} |
| | | |
| | | this.setState({ |
| | | card: _card |
| | | }) |
| | | |
| | | this.props.updateConfig(_card) |
| | | } |
| | | |
| | | changeStyle = () => { |
| | | const { card } = this.state |
| | | |
| | | MKEmitter.emit('changeStyle', [card.uuid], ['font', 'background', 'border', 'padding', 'shadow'], card.style) |
| | | } |
| | | |
| | | clickComponent = (e) => { |
| | | if (sessionStorage.getItem('style-control') === 'true' || sessionStorage.getItem('style-control') === 'component') { |
| | | e.stopPropagation() |
| | | MKEmitter.emit('clickComponent', this.state.card) |
| | | } |
| | | } |
| | | |
| | | changeMenu = (menu) => { |
| | | if (menu.property === 'link') { |
| | | window.open(menu.link) |
| | | } else { |
| | | MKEmitter.emit('changeEditMenu', { |
| | | fixed: menu.property === 'menu', |
| | | MenuID: menu.property === 'linkmenu' ? menu.linkMenuId : menu.MenuID, |
| | | copyMenuId: menu.property === 'menu' ? menu.copyMenuId : '', |
| | | MenuNo: menu.MenuNo, |
| | | MenuName: menu.name, |
| | | }) |
| | | } |
| | | } |
| | | |
| | | render() { |
| | | const { card } = this.state |
| | | |
| | | let _style = {...card.style} |
| | | if (_style.shadow) { |
| | | _style.boxShadow = '0 0 4px ' + _style.shadow |
| | | } |
| | | _style.height = card.wrap.height |
| | | |
| | | return ( |
| | | <div className="normal-topbar-edit-box" style={_style} onClick={this.clickComponent} id={card.uuid}> |
| | | <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={ |
| | | <div className="mk-popover-control"> |
| | | <WrapComponent config={card} updateConfig={this.updateComponent} /> |
| | | <Icon className="style" title="调整样式" onClick={this.changeStyle} type="font-colors" /> |
| | | <Icon className="close" title="删除组件" type="delete" onClick={() => this.props.deletecomponent(card.uuid)} /> |
| | | </div> |
| | | } trigger="hover"> |
| | | <Icon type="tool" /> |
| | | </Popover> |
| | | <div className="am-navbar"> |
| | | <div className="am-navbar-left"> |
| | | <Icon type="left" /> |
| | | </div> |
| | | <div className="am-navbar-title">{card.wrap.title || ''}</div> |
| | | <div className="am-navbar-right"></div> |
| | | </div> |
| | | </div> |
| | | ) |
| | | } |
| | | } |
| | | |
| | | export default NormalNavbar |
New file |
| | |
| | | .normal-topbar-edit-box { |
| | | position: fixed; |
| | | top: 0px; |
| | | left: 0px; |
| | | width: 100%; |
| | | box-sizing: border-box; |
| | | background: #ffffff; |
| | | background-position: center center; |
| | | background-repeat: no-repeat; |
| | | background-size: cover; |
| | | min-height: 30px; |
| | | z-index: 3; |
| | | |
| | | .anticon-tool { |
| | | position: absolute; |
| | | z-index: 2; |
| | | font-size: 16px; |
| | | right: 1px; |
| | | top: 1px; |
| | | cursor: pointer; |
| | | padding: 5px; |
| | | background: rgba(255, 255, 255, 0.55); |
| | | color: rgba(0, 0, 0, 0.65); |
| | | } |
| | | .am-navbar { |
| | | height: 100%; |
| | | display: flex; |
| | | font-style: inherit; |
| | | font-weight: inherit; |
| | | .am-navbar-left { |
| | | flex: 1; |
| | | text-align: left; |
| | | } |
| | | .am-navbar-title { |
| | | text-align: center; |
| | | font-style: inherit; |
| | | font-weight: inherit; |
| | | flex: 1; |
| | | } |
| | | .am-navbar-right { |
| | | flex: 1; |
| | | } |
| | | } |
| | | } |
| | | .normal-topbar-edit-box::after { |
| | | display: block; |
| | | content: ' '; |
| | | clear: both; |
| | | } |
| | | .normal-topbar-edit-box:hover { |
| | | box-shadow: 0px 0px 4px #1890ff; |
| | | } |
New file |
| | |
| | | import React, {Component} from 'react' |
| | | import PropTypes from 'prop-types' |
| | | import { is, fromJS } from 'immutable' |
| | | import { Icon, Modal } from 'antd' |
| | | |
| | | import zhCN from '@/locales/zh-CN/model.js' |
| | | import enUS from '@/locales/en-US/model.js' |
| | | import SettingForm from './settingform' |
| | | import './index.scss' |
| | | |
| | | class DataSource extends Component { |
| | | static propTpyes = { |
| | | config: PropTypes.any, |
| | | updateConfig: PropTypes.func |
| | | } |
| | | |
| | | state = { |
| | | dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS, |
| | | visible: false, |
| | | wrap: null |
| | | } |
| | | |
| | | UNSAFE_componentWillMount () { |
| | | const { config } = this.props |
| | | |
| | | this.setState({wrap: fromJS(config.wrap).toJS()}) |
| | | } |
| | | |
| | | shouldComponentUpdate (nextProps, nextState) { |
| | | return !is(fromJS(this.props), fromJS(nextProps)) || !is(fromJS(this.state), fromJS(nextState)) |
| | | } |
| | | |
| | | editDataSource = () => { |
| | | this.setState({ |
| | | visible: true |
| | | }) |
| | | } |
| | | |
| | | verifySubmit = () => { |
| | | const { config } = this.props |
| | | |
| | | this.verifyRef.handleConfirm().then(res => { |
| | | |
| | | this.setState({ |
| | | wrap: res, |
| | | visible: false |
| | | }) |
| | | this.props.updateConfig({...config, wrap: res}) |
| | | }) |
| | | } |
| | | |
| | | render () { |
| | | const { visible, dict, wrap } = this.state |
| | | |
| | | return ( |
| | | <div className="model-menu-setting-wrap"> |
| | | <Icon type="edit" title="编辑" onClick={() => this.editDataSource()} /> |
| | | <Modal |
| | | wrapClassName="popview-modal" |
| | | title="导航栏设置" |
| | | visible={visible} |
| | | width={600} |
| | | maskClosable={false} |
| | | okText={dict['model.submit']} |
| | | onOk={this.verifySubmit} |
| | | onCancel={() => { this.setState({ visible: false }) }} |
| | | destroyOnClose |
| | | > |
| | | <SettingForm |
| | | dict={dict} |
| | | wrap={wrap} |
| | | inputSubmit={this.verifySubmit} |
| | | wrappedComponentRef={(inst) => this.verifyRef = inst} |
| | | /> |
| | | </Modal> |
| | | </div> |
| | | ) |
| | | } |
| | | } |
| | | |
| | | export default DataSource |
New file |
| | |
| | | .model-menu-setting-wrap { |
| | | display: inline-block; |
| | | |
| | | >.anticon-edit { |
| | | color: #1890ff; |
| | | } |
| | | } |
New file |
| | |
| | | import React, {Component} from 'react' |
| | | import PropTypes from 'prop-types' |
| | | import { Form, Row, Col, Input, InputNumber } from 'antd' |
| | | |
| | | import './index.scss' |
| | | |
| | | class SettingForm extends Component { |
| | | static propTpyes = { |
| | | dict: PropTypes.object, // 字典项 |
| | | wrap: PropTypes.object, // 数据源配置 |
| | | inputSubmit: PropTypes.func // 回车事件 |
| | | } |
| | | |
| | | state = {} |
| | | |
| | | handleConfirm = () => { |
| | | // 表单提交时检查输入值是否正确 |
| | | return new Promise((resolve, reject) => { |
| | | this.props.form.validateFieldsAndScroll((err, values) => { |
| | | if (!err) { |
| | | resolve(values) |
| | | } else { |
| | | reject(err) |
| | | } |
| | | }) |
| | | }) |
| | | } |
| | | |
| | | handleSubmit = (e) => { |
| | | e.preventDefault() |
| | | |
| | | if (this.props.inputSubmit) { |
| | | this.props.inputSubmit() |
| | | } |
| | | } |
| | | |
| | | render() { |
| | | const { wrap } = this.props |
| | | const { getFieldDecorator } = this.props.form |
| | | const formItemLayout = { |
| | | labelCol: { |
| | | xs: { span: 24 }, |
| | | sm: { span: 8 } |
| | | }, |
| | | wrapperCol: { |
| | | xs: { span: 24 }, |
| | | sm: { span: 16 } |
| | | } |
| | | } |
| | | |
| | | return ( |
| | | <div className="model-menu-setting-form"> |
| | | <Form {...formItemLayout}> |
| | | <Row gutter={24}> |
| | | <Col span={22}> |
| | | <Form.Item label="标题"> |
| | | {getFieldDecorator('title', { |
| | | initialValue: wrap.title || '' |
| | | })(<Input placeholder={''} autoComplete="off" onPressEnter={this.handleSubmit} />)} |
| | | </Form.Item> |
| | | </Col> |
| | | <Col span={22}> |
| | | <Form.Item label="高度"> |
| | | {getFieldDecorator('height', { |
| | | initialValue: wrap.height || 50, |
| | | rules: [ |
| | | { |
| | | required: true, |
| | | message: this.props.dict['form.required.input'] + '高度!' |
| | | } |
| | | ] |
| | | })(<InputNumber min={30} max={200} precision={0} onPressEnter={this.handleSubmit} />)} |
| | | </Form.Item> |
| | | </Col> |
| | | </Row> |
| | | </Form> |
| | | </div> |
| | | ) |
| | | } |
| | | } |
| | | |
| | | export default Form.create()(SettingForm) |
New file |
| | |
| | | .model-menu-setting-form { |
| | | position: relative; |
| | | |
| | | .anticon-question-circle { |
| | | color: #c49f47; |
| | | margin-right: 3px; |
| | | } |
| | | .ant-input-number { |
| | | width: 100%; |
| | | } |
| | | } |
| | |
| | | const CodeSandbox = asyncComponent(() => import('@/menu/components/code/sandbox')) |
| | | const NormalLogin = asyncComponent(() => import('@/pc/components/login/normal-login')) |
| | | const NormalNavbar = asyncComponent(() => import('@/mob/components/navbar/normal-navbar')) |
| | | const NormalTopbar = asyncComponent(() => import('@/mob/components/topbar/normal-navbar')) |
| | | |
| | | const Card = ({ id, card, moveCard, findCard, delCard, updateConfig }) => { |
| | | const originalIndex = findCard(id).index |
| | |
| | | } |
| | | |
| | | let col = 'ant-col-' + (card.width || 24) |
| | | if (card.type === 'navbar') { |
| | | if (card.type === 'navbar' || card.type === 'topbar') { |
| | | col = '' |
| | | } else if (card.type === 'login') { |
| | | let height = '' |
| | |
| | | return (<NormalLogin card={card} updateConfig={updateConfig} deletecomponent={delCard}/>) |
| | | } else if (card.type === 'navbar') { |
| | | return (<NormalNavbar card={card} updateConfig={updateConfig} deletecomponent={delCard}/>) |
| | | } else if (card.type === 'topbar') { |
| | | return (<NormalTopbar card={card} updateConfig={updateConfig} deletecomponent={delCard}/>) |
| | | } |
| | | } |
| | | |
| | |
| | | let uuids = MenuUtils.getDelButtonIds(card) |
| | | |
| | | confirm({ |
| | | title: `确定删除《${card.name}》吗?`, |
| | | title: `确定删除${card.name ? `《${card.name}》` : '组件'}吗?`, |
| | | content: hasComponent ? '当前组件中含有子组件!' : '', |
| | | onOk() { |
| | | MKEmitter.emit('delButtons', uuids) |
| | |
| | | dashboard: '仪表盘', |
| | | form: '表单', |
| | | card: '卡片', |
| | | navbar: '导航栏', |
| | | login: '登录' |
| | | } |
| | | let i = 1 |
| | |
| | | import form from '@/assets/mobimg/form.png' |
| | | import Login from '@/assets/mobimg/login.png' |
| | | import dashboard from '@/assets/mobimg/dashboard.png' |
| | | import NavTop from '@/assets/mobimg/navtop-mob.png' |
| | | |
| | | // 组件配置信息 |
| | | export const menuOptions = [ |
| | | { type: 'menu', url: Navbar, component: 'navbar', subtype: 'mobnavbar', title: '导航栏', width: 1200 }, |
| | | { type: 'menu', url: NavTop, component: 'topbar', subtype: 'topbar', title: '导航栏' }, |
| | | { type: 'menu', url: Navbar, component: 'navbar', subtype: 'tabbar', title: '菜单栏' }, |
| | | { type: 'menu', url: tabs, component: 'tabs', subtype: 'tabs', title: '标签页', width: 24 }, |
| | | { type: 'menu', url: Mainsearch, component: 'search', subtype: 'mainsearch', title: '搜索条件', width: 24 }, |
| | | { type: 'menu', url: card1, component: 'card', subtype: 'datacard', title: '数据卡', width: 24 }, |
| | |
| | | } |
| | | |
| | | render() { |
| | | const { config } = this.props |
| | | const { columns, setting, scripts, colColumns, activeKey, loading } = this.state |
| | | |
| | | return ( |
| | |
| | | wrappedComponentRef={(inst) => this.contrastForm = inst} |
| | | /> |
| | | <FieldsComponent |
| | | config={{...this.props.config, columns}} |
| | | config={{...config, columns}} |
| | | type="fields" |
| | | updatefield={this.updatefields} |
| | | /> |
| | |
| | | dict={this.props.dict} |
| | | setting={setting} |
| | | scripts={scripts} |
| | | urlFields={config.urlFields} |
| | | defaultSql={this.state.defaultsql} |
| | | searches={this.props.searches} |
| | | scriptsChange={this.scriptsChange} |
| | |
| | | setting={setting} |
| | | scripts={scripts} |
| | | defaultSql={defaultSql} |
| | | urlFields={config.urlFields} |
| | | searches={this.props.search} |
| | | scriptsChange={this.scriptsChange} |
| | | scriptsUpdate={this.scriptsUpdate} |
| | |
| | | setting={setting} |
| | | scripts={preScripts} |
| | | regoptions={regoptions} |
| | | urlFields={config.urlFields} |
| | | searches={this.props.search} |
| | | scriptsUpdate={this.preScriptsUpdate} |
| | | wrappedComponentRef={(inst) => this.preScriptsForm = inst} |
| | |
| | | setting: PropTypes.object, // 设置 |
| | | scripts: PropTypes.array, // 自定义脚本列表 |
| | | searches: PropTypes.array, // 搜索条件 |
| | | urlFields: PropTypes.any, // url变量 |
| | | regoptions: PropTypes.any, // 正则替换 |
| | | scriptsChange: PropTypes.func, // 自定义脚本切换时验证 |
| | | scriptsUpdate: PropTypes.func // 表单 |
| | |
| | | } |
| | | |
| | | UNSAFE_componentWillMount() { |
| | | const { searches, scripts } = this.props |
| | | const { searches, scripts, urlFields } = this.props |
| | | |
| | | let _usefulFields = [] |
| | | let scriptsColumns = fromJS(this.state.scriptsColumns).toJS() |
| | |
| | | _usefulFields.push(item.field) |
| | | } |
| | | }) |
| | | |
| | | if (urlFields) { |
| | | _usefulFields.push(...urlFields) |
| | | } |
| | | |
| | | _usefulFields = _usefulFields.join(', ') |
| | | scriptsColumns = scriptsColumns.filter(item => { |
| | | if (item.dataIndex === 'sql') { |
| | |
| | | setting: PropTypes.object, // 设置 |
| | | scripts: PropTypes.array, // 自定义脚本列表 |
| | | searches: PropTypes.array, // 搜索条件 |
| | | urlFields: PropTypes.any, // url变量 |
| | | defaultSql: PropTypes.string, // 默认sql |
| | | scriptsChange: PropTypes.func, // 自定义脚本切换时验证 |
| | | scriptsUpdate: PropTypes.func // 表单 |
| | |
| | | } |
| | | |
| | | UNSAFE_componentWillMount() { |
| | | const { searches, scripts } = this.props |
| | | const { searches, scripts, urlFields } = this.props |
| | | |
| | | let _usefulFields = [] |
| | | searches.forEach(item => { |
| | |
| | | } |
| | | }) |
| | | |
| | | if (urlFields) { |
| | | _usefulFields.push(...urlFields) |
| | | } |
| | | |
| | | this.setState({ |
| | | usefulFields: _usefulFields.join(', '), |
| | | scripts: fromJS(scripts).toJS() |
| | |
| | | import PropTypes from 'prop-types' |
| | | import { is, fromJS } from 'immutable' |
| | | import { DndProvider, DragSource, DropTarget } from 'react-dnd' |
| | | import { Table, Input, InputNumber, Popconfirm, Form, Icon, Select, Radio, Cascader, notification, message, Modal } from 'antd' |
| | | import { Table, Input, InputNumber, Popconfirm, Form, Icon, Select, Radio, Cascader, notification, message, Modal, Typography } from 'antd' |
| | | |
| | | import Utils from '@/utils/utils.js' |
| | | import ColorSketch from '@/mob/colorsketch' |
| | |
| | | let eTDict = sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS |
| | | const EditableContext = React.createContext() |
| | | let dragingIndex = -1 |
| | | const { Paragraph } = Typography |
| | | |
| | | class BodyRow extends React.Component { |
| | | render() { |
| | |
| | | } |
| | | |
| | | const columns = this.state.columns.map(col => { |
| | | if (col.copy) { |
| | | col.render = (text) => (<Paragraph copyable>{text}</Paragraph>) |
| | | } |
| | | if (!col.editable) return col |
| | | return { |
| | | ...col, |
| | |
| | | 'alipay', |
| | | ], |
| | | normal: [ |
| | | 'user', |
| | | 'account-book', |
| | | 'alert', |
| | | 'api', |
| | |
| | | 'key', |
| | | 'man', |
| | | 'woman', |
| | | 'team', |
| | | 'poweroff', |
| | | 'search', |
| | | 'shopping-cart', |
| | |
| | | error = `组件《${item.name}》未设置数据源!` |
| | | } else if (item.setting.interType === 'system' && item.setting.execute === 'false' && item.scripts.length === 0) { |
| | | error = `组件《${item.name}》未设置数据源!` |
| | | } else if (!item.setting.primaryKey && MenuType !== 'billPrint') { |
| | | } else if (!item.setting.primaryKey && MenuType !== 'billPrint' && item.subtype !== 'propcard') { |
| | | error = `组件《${item.name}》未设置主键!` |
| | | } |
| | | } |
| | |
| | | } else if (item.type === 'group') { |
| | | check(item.components) |
| | | return |
| | | } else if (item.type === 'navbar' && !item.wrap.MenuNo) { |
| | | error = `导航栏《${item.name}》未设置菜单参数!` |
| | | } |
| | | if (['propcard', 'brafteditor', 'sandbox'].includes(item.subtype) && item.wrap.datatype === 'static') return |
| | | |
| | | if (['propcard', 'brafteditor', 'sandbox', 'tabbar'].includes(item.subtype) && item.wrap.datatype === 'static') return |
| | | |
| | | if (item.setting) { |
| | | if (item.setting.interType === 'system' && item.setting.execute !== 'false' && !item.setting.dataresource) { |
| | | error = `组件《${item.name}》未设置数据源!` |
| | | } else if (item.setting.interType === 'system' && item.setting.execute === 'false' && item.scripts.length === 0) { |
| | | error = `组件《${item.name}》未设置数据源!` |
| | | } else if (!item.setting.primaryKey) { |
| | | } else if (!item.setting.primaryKey && !['propcard', 'tabbar'].includes(item.subtype)) { |
| | | error = `组件《${item.name}》未设置主键!` |
| | | } |
| | | } |
| | |
| | | error = `组件《${item.name}》未设置数据源!` |
| | | } else if (item.setting.interType === 'system' && item.setting.execute === 'false' && item.scripts.length === 0) { |
| | | error = `组件《${item.name}》未设置数据源!` |
| | | } else if (!item.setting.primaryKey) { |
| | | } else if (!item.setting.primaryKey && item.subtype !== 'propcard') { |
| | | error = `组件《${item.name}》未设置主键!` |
| | | } |
| | | } |