src/api/index.js
@@ -373,7 +373,7 @@ * @description 获取或修改云端配置 */ getCloudConfig (param) { param.lang = localStorage.getItem('lang') || '' param.lang = param.lang || localStorage.getItem('lang') || '' param.appkey = window.GLOB.appkey || '' param.SessionUid = localStorage.getItem('SessionUid') || '' @@ -403,7 +403,7 @@ * @description 获取云端配置,并缓存信息 */ getCloudCacheConfig (param) { param.lang = localStorage.getItem('lang') || '' param.lang = param.lang || localStorage.getItem('lang') || '' param.appkey = window.GLOB.appkey || '' param.SessionUid = localStorage.getItem('SessionUid') || '' @@ -452,7 +452,7 @@ */ getSystemConfig (param) { param.userid = sessionStorage.getItem('UserID') || '' param.lang = localStorage.getItem('lang') || '' param.lang = param.lang || localStorage.getItem('lang') || '' param.SessionUid = localStorage.getItem('SessionUid') || '' param.LoginUID = sessionStorage.getItem('LoginUID') || '' param.appkey = window.GLOB.appkey || '' @@ -479,7 +479,7 @@ */ getLocalConfig (param) { param.userid = sessionStorage.getItem('UserID') || '' param.lang = localStorage.getItem('lang') || '' param.lang = param.lang || localStorage.getItem('lang') || '' param.SessionUid = localStorage.getItem('SessionUid') || '' param.LoginUID = sessionStorage.getItem('LoginUID') || '' param.appkey = window.GLOB.appkey || '' @@ -499,7 +499,7 @@ */ getCacheConfig (param) { param.userid = sessionStorage.getItem('UserID') || '' param.lang = localStorage.getItem('lang') || '' param.lang = param.lang || localStorage.getItem('lang') || '' param.SessionUid = localStorage.getItem('SessionUid') || '' param.LoginUID = sessionStorage.getItem('LoginUID') || '' param.appkey = window.GLOB.appkey || '' @@ -593,7 +593,7 @@ */ getLocalCacheConfig (param) { param.userid = sessionStorage.getItem('UserID') || '' param.lang = localStorage.getItem('lang') || '' param.lang = param.lang || localStorage.getItem('lang') || '' param.SessionUid = localStorage.getItem('SessionUid') || '' param.LoginUID = sessionStorage.getItem('LoginUID') || '' param.appkey = window.GLOB.appkey || '' @@ -650,7 +650,7 @@ */ getSystemCacheConfig (param) { param.userid = param.userid || sessionStorage.getItem('UserID') || '' param.lang = localStorage.getItem('lang') || '' param.lang = param.lang || localStorage.getItem('lang') || '' param.SessionUid = localStorage.getItem('SessionUid') || '' param.LoginUID = param.LoginUID || sessionStorage.getItem('LoginUID') || '' param.appkey = window.GLOB.appkey || '' src/menu/components/card/cardcellcomponent/index.jsx
@@ -558,6 +558,9 @@ dropButton = (id) => { const { cards } = this.props if (!cards.action) return let index = cards.action.findIndex(item => item.uuid === id) if (index === -1) return src/menu/datasource/verifycard/settingform/index.jsx
@@ -315,7 +315,7 @@ {config.format === 'array' ? <Col span={8}> <Form.Item label="默认排序"> {getFieldDecorator('order', { initialValue: setting.order || '', initialValue: setting.order || 'ID asc', rules: [ { required: true, src/mob/datasource/verifycard/settingform/index.jsx
@@ -286,7 +286,7 @@ {structure === 'array' ? <Col span={8}> <Form.Item label="默认排序"> {getFieldDecorator('order', { initialValue: setting.order || '' initialValue: setting.order || 'ID asc' })(<Input placeholder={'ID asc, UID desc'} autoComplete="off" />)} </Form.Item> </Col> : null} src/mob/header/index.jsx
@@ -19,7 +19,6 @@ view: PropTypes.string, saveIng: PropTypes.any, triggerSave: PropTypes.func, jumpToManage: PropTypes.func } state = { @@ -64,11 +63,6 @@ theme="dark" inlineCollapsed={this.state.collapsed} > <Menu.Item key="1"> <Tooltip placement="bottom" title="返回应用管理"> <Icon type="arrow-left" onClick={this.props.jumpToManage} /> </Tooltip> </Menu.Item> <Menu.Item key="2"> <Tooltip placement="bottom" title="保存"> <Button icon="save" loading={this.props.saveIng} onClick={this.props.triggerSave}></Button> src/pc/bgcontroller/index.jsx
New file @@ -0,0 +1,103 @@ import React, {Component} from 'react' import PropTypes from 'prop-types' import { is, fromJS } from 'immutable' import { Form } from 'antd' import zhCN from '@/locales/zh-CN/mob.js' import enUS from '@/locales/en-US/mob.js' import asyncComponent from '@/utils/asyncComponent' import './index.scss' const ColorSketch = asyncComponent(() => import('@/mob/colorsketch')) const SourceComponent = asyncComponent(() => import('@/menu/components/share/sourcecomponent')) class MobController extends Component { static propTpyes = { config: PropTypes.any, updateConfig: PropTypes.func, } state = { dict: localStorage.getItem('lang') !== 'en-US' ? zhCN : enUS, backgroundColor: '', backgroundImage: '', } UNSAFE_componentWillMount () { const { config } = this.props let bgImg = config.style.backgroundImage || '' if (bgImg && /^url/.test(bgImg)) { bgImg = bgImg.replace('url(', '') bgImg = bgImg.replace(')', '') } this.setState({ backgroundColor: config.style.backgroundColor, backgroundImage: bgImg }) } shouldComponentUpdate (nextProps, nextState) { return !is(fromJS(this.state), fromJS(nextState)) } /** * @description 修改背景颜色 ,颜色控件 */ changeBackgroundColor = (val) => { let config = fromJS(this.props.config).toJS() this.setState({ backgroundColor: val }) config.style.backgroundColor = val this.props.updateConfig(config) } imgChange = (val) => { this.setState({ backgroundImage: val }) let config = fromJS(this.props.config).toJS() if (val) { config.style.backgroundImage = `url(${val})` } else { delete config.style.backgroundImage } this.props.updateConfig(config) } render () { const { backgroundColor, backgroundImage } = this.state const formItemLayout = { labelCol: { xs: { span: 24 }, sm: { span: 4 } }, wrapperCol: { xs: { span: 24 }, sm: { span: 20 } } } return ( <div className="menu-background-controller"> <Form {...formItemLayout}> <Form.Item className="color-control" colon={false} label="颜色"> <ColorSketch value={backgroundColor} onChange={this.changeBackgroundColor} /> </Form.Item> <Form.Item colon={false} label="图片"> <SourceComponent value={backgroundImage} type="" placement="right" onChange={this.imgChange}/> </Form.Item> </Form> </div> ) } } export default MobController src/pc/bgcontroller/index.scss
New file @@ -0,0 +1,43 @@ .menu-background-controller { width: 100%; height: 100%; overflow: hidden; .color-control .ant-form-item-control { padding-top: 10px; line-height: 35px; } .mk-source-wrap { height: 32px; .mk-source-item-info { top: 5px; } } } .margin-popover { padding-top: 0px; .ant-popover-inner-content { width: 90px; padding: 0px 5px; .ant-menu-root.ant-menu-vertical { border: 0; .ant-menu-item { height: 30px; cursor: pointer; line-height: 30px; } .ant-menu-item:not(:last-child) { margin-bottom: 0px; } .ant-menu-item:first-child { margin-top: 10px; } .ant-menu-item:last-child { margin-bottom: 10px; } } } .ant-popover-arrow { display: none; } } src/pc/padcontroller/index.jsx
New file @@ -0,0 +1,105 @@ import React, {Component} from 'react' import PropTypes from 'prop-types' import { is, fromJS } from 'immutable' import { Form, Col, Icon } from 'antd' import zhCN from '@/locales/zh-CN/mob.js' import enUS from '@/locales/en-US/mob.js' import StyleInput from '@/menu/stylecontroller/styleInput' import './index.scss' class MobController extends Component { static propTpyes = { config: PropTypes.any, updateConfig: PropTypes.func, } state = { dict: localStorage.getItem('lang') !== 'en-US' ? zhCN : enUS, paddingTop: '', paddingBottom: '', paddingLeft: '', paddingRight: '' } UNSAFE_componentWillMount () { } shouldComponentUpdate (nextProps, nextState) { return !is(fromJS(this.state), fromJS(nextState)) } /** * @description 修改背景颜色 ,颜色控件 */ changePadding = (val, type) => { let config = fromJS(this.props.config).toJS() config.style[type] = val this.props.updateConfig(config) } render () { const { config } = this.props const formItemLayout = { labelCol: { xs: { span: 24 }, sm: { span: 4 } }, wrapperCol: { xs: { span: 24 }, sm: { span: 20 } } } return ( <div className="menu-padding-controller"> <Form {...formItemLayout}> <Col span={24}> <Form.Item colon={false} label={<Icon title="宽度" type="column-width" />} > <StyleInput defaultValue={config.style.width || '100%'} options={['px', '%', 'vw']} onChange={(val) => this.changePadding(val, 'width')}/> </Form.Item> </Col> <Col span={24}> <Form.Item colon={false} label={<Icon title="上边距" type="arrow-up"/>} > <StyleInput defaultValue={config.style.paddingTop || '0px'} options={['px', 'vh', 'vw']} onChange={(val) => this.changePadding(val, 'paddingTop')}/> </Form.Item> </Col> <Col span={24}> <Form.Item colon={false} label={<Icon title="下边距" type="arrow-down"/>} > <StyleInput defaultValue={config.style.paddingBottom || '0px'} options={['px', 'vh', 'vw']} onChange={(val) => this.changePadding(val, 'paddingBottom')}/> </Form.Item> </Col> <Col span={24}> <Form.Item colon={false} label={<Icon title="左边距" type="arrow-left"/>} > <StyleInput defaultValue={config.style.paddingLeft || '0px'} options={['px', 'vh', 'vw']} onChange={(val) => this.changePadding(val, 'paddingLeft')}/> </Form.Item> </Col> <Col span={24}> <Form.Item colon={false} label={<Icon title="右边距" type="arrow-right"/>} > <StyleInput defaultValue={config.style.paddingRight || '0px'} options={['px', 'vh', 'vw']} onChange={(val) => this.changePadding(val, 'paddingRight')}/> </Form.Item> </Col> </Form> </div> ) } } export default MobController src/pc/padcontroller/index.scss
New file @@ -0,0 +1,9 @@ .menu-padding-controller { width: 100%; height: 100%; overflow: hidden; .ant-form-item label > .anticon { font-size: 16px; vertical-align: middle; } } src/router/index.js
@@ -12,7 +12,8 @@ const Design = asyncLoadComponent(() => import('@/views/design')) const Login = asyncLoadComponent(() => import('@/views/login')) const NotFound = asyncComponent(() => import('@/views/404')) const MobManage = asyncLoadComponent(() => import('@/views/mobmanage')) const AppManage = asyncLoadComponent(() => import('@/views/appmanage')) const PCDesign = asyncLoadComponent(() => import('@/views/pcdesign')) const MobDesign = asyncLoadComponent(() => import('@/views/mobdesign')) const MenuDesign = asyncLoadComponent(() => import('@/views/menudesign')) const BillPrint = asyncLoadComponent(() => import('@/views/billprint')) @@ -25,8 +26,9 @@ {path: '/ssologin/:param', name: 'ssologin', component: Sso, auth: false}, {path: '/main', name: 'main', component: Main, auth: true}, {path: '/design', name: 'design', component: Design, auth: true}, {path: '/mobmanage', name: 'mobmanage', component: MobManage, auth: true}, {path: '/mobdesign/:appId/:appType/:appCode/:appName', name: 'mobdesign', component: MobDesign, auth: true}, {path: '/appmanage', name: 'appmanage', component: AppManage, auth: true}, {path: '/pcdesign/:param', name: 'pcdesign', component: PCDesign, auth: true}, {path: '/mobdesign/:param', name: 'mobdesign', component: MobDesign, auth: true}, {path: '/menudesign/:param', name: 'menudesign', component: MenuDesign, auth: true}, {path: '/billprint/:param', name: 'billprint', component: BillPrint, auth: true}, {path: '/paramsmain/:param', name: 'pmain', component: Main, auth: true} src/tabviews/zshare/settingcomponent/editTable/index.jsx
@@ -21,7 +21,7 @@ if (inputType === 'select') { let _options = [] if (record.$port) { _options = window.GLOB.UserCacheMap.get(record.$port) _options = window.GLOB.UserCacheMap.get(record.$port) || [] } return ( <Select allowClear> src/templates/sharecomponent/settingcomponent/settingform/datasource/index.jsx
@@ -465,7 +465,7 @@ <Col span={12}> <Form.Item label="默认排序"> {getFieldDecorator('order', { initialValue: setting.order || '', initialValue: setting.order || 'ID asc', rules: [ { required: true, src/views/appmanage/index.jsx
File was renamed from src/views/mobmanage/index.jsx @@ -231,7 +231,14 @@ } jumpApp = (item) => { console.log(item) const { selectApp } = this.state let route = 'mobdesign' if (item.typename === 'pc') { route = 'pcdesign' } window.open(window.location.href.replace(/#.+/ig, `#/${route}/${window.btoa(window.encodeURIComponent(JSON.stringify({...item, kei_no: selectApp.kei_no, remark: selectApp.remark, type: 'app'})))}`)) } /** @@ -262,7 +269,6 @@ * @description 点击整行,触发切换, 判断是否可选,单选或多选,进行对应操作 */ changeSubRow = (record) => { console.log(record) this.setState({ selectedSubRowKeys: [record.ID], selectSubApp: record }) } @@ -370,7 +376,7 @@ const { selectApp, subVisible, selectSubApp } = this.state this.submobcardRef.handleConfirm().then(res => { if (subVisible === 'plus' && selectApp.sublist.filter(item => item.typename === res.typename).length > 0) { if (subVisible === 'plus' && selectApp.sublist.filter(item => item.typename === res.typename && item.lang === res.lang).length > 0) { notification.warning({ top: 92, message: '应用类型已存在!', src/views/appmanage/index.scss
src/views/appmanage/mutilform/index.jsx
File was renamed from src/views/mobmanage/mutilform/index.jsx @@ -43,7 +43,7 @@ }, wrapperCol: { xs: { span: 24 }, sm: { span: 16 } sm: { span: 12 } } } return ( src/views/appmanage/mutilform/index.scss
src/views/appmanage/submutilform/index.jsx
File was renamed from src/views/mobmanage/submutilform/index.jsx @@ -43,7 +43,7 @@ }, wrapperCol: { xs: { span: 24 }, sm: { span: 16 } sm: { span: 12 } } } return ( @@ -52,13 +52,7 @@ <Col span={24}> <Form.Item label="应用类型"> {getFieldDecorator('typename', { initialValue: card ? card.typename : 'mob', rules: [ { required: true, message: '请选择应用类型!' } ] initialValue: card ? card.typename : 'mob' })( <Select disabled={type === 'edit'}> <Select.Option value="mob">移动端(包括android、ios)</Select.Option> @@ -72,7 +66,7 @@ {getFieldDecorator('lang', { initialValue: card ? card.lang || 'zh-CN' : 'zh-CN' })( <Radio.Group> <Radio.Group disabled={type === 'edit'}> <Radio value="zh-CN">中文</Radio> <Radio value="en-US">英文</Radio> </Radio.Group> src/views/appmanage/submutilform/index.scss
src/views/design/header/index.jsx
@@ -328,9 +328,9 @@ {editLevel === 'HS' ? <Button className="level4-close" type="primary" onClick={this.exitManage}>退出</Button> : null} {/* 进入编辑按钮 */} {!editLevel ? <Icon onClick={this.enterEdit} className="edit-check" type="edit" /> : null} {/* {!editLevel && options.sysType === 'local' && window.GLOB.systemType !== 'production' ? <a href="#/mobmanage" target="_blank" className="mobile" type="edit"> 应用管理 <Icon type="arrow-right" /></a> : null } */} {!editLevel && options.sysType === 'local' && window.GLOB.systemType !== 'production' ? <a href="#/appmanage" target="_blank" className="mobile" type="edit"> 应用管理 <Icon type="arrow-right" /></a> : null } {/* window.btoa(window.encodeURIComponent(JSON.stringify({ MenuType: 'home', MenuId: 'home_page_id', MenuName: '首页' }))) */} {!editLevel && window.GLOB.systemType !== 'production' && this.props.memberLevel >= 20 ? <a className="home-edit" href={`#/menudesign/JTdCJTIyTWVudVR5cGUlMjIlM0ElMjJob21lJTIyJTJDJTIyTWVudUlkJTIyJTNBJTIyaG9tZV9wYWdlX2lkJTIyJTJDJTIyTWVudU5hbWUlMjIlM0ElMjIlRTklQTYlOTYlRTklQTElQjUlMjIlN0Q=`} target="_blank" rel="noopener noreferrer"> src/views/mobdesign/index.jsx
@@ -1,7 +1,7 @@ import React, { Component } from 'react' import { connect } from 'react-redux' import { DndProvider } from 'react-dnd' import { is, fromJS } from 'immutable' import { fromJS } from 'immutable' import moment from 'moment' import HTML5Backend from 'react-dnd-html5-backend' import { Icon, Tabs, notification, Modal } from 'antd' @@ -50,26 +50,6 @@ componentWillUnmount () { this.setState = () => { return } } jumpToManage = () => { const { oriConfig, config } = this.state const _this = this if (!is(fromJS(oriConfig), fromJS(config))) { confirm({ title: '配置已修改,放弃保存吗?', content: '', okText: _this.state.dict['mob.confirm'], cancelText: _this.state.dict['mob.cancel'], onOk() { _this.props.history.replace('/mobmanage') }, onCancel() {} }) } else { _this.props.history.replace('/mobmanage') } } src/views/pcdesign/index.jsx
New file @@ -0,0 +1,989 @@ import React, { Component } from 'react' import { connect } from 'react-redux' import { DndProvider } from 'react-dnd' import { is, fromJS } from 'immutable' import moment from 'moment' import HTML5Backend from 'react-dnd-html5-backend' import { ConfigProvider, notification, Modal, Collapse, Switch, Button, Icon } from 'antd' // import html2canvas from 'html2canvas' import Api from '@/api' // import options from '@/store/options.js' import Utils from '@/utils/utils.js' import zhCN from '@/locales/zh-CN/mob.js' import enUS from '@/locales/en-US/mob.js' import antdEnUS from 'antd/es/locale/en_US' import antdZhCN from 'antd/es/locale/zh_CN' import MKEmitter from '@/utils/events.js' import MenuUtils from '@/menu/utils/menuUtils.js' import asyncComponent from '@/utils/asyncComponent' import { modifyCustomMenu } from '@/store/action' import './index.scss' const { Panel } = Collapse const { confirm } = Modal const _locale = localStorage.getItem('lang') !== 'en-US' ? antdZhCN : antdEnUS const MenuForm = asyncComponent(() => import('./menuform')) const MenuShell = asyncComponent(() => import('@/menu/menushell')) const SourceWrap = asyncComponent(() => import('@/menu/modulesource')) const BgController = asyncComponent(() => import('@/pc/bgcontroller')) const PasteController = asyncComponent(() => import('@/menu/pastecontroller')) const PaddingController = asyncComponent(() => import('@/pc/padcontroller')) const StyleController = asyncComponent(() => import('@/menu/stylecontroller')) const SysInterface = asyncComponent(() => import('@/menu/sysinterface')) const PictureController = asyncComponent(() => import('@/menu/picturecontroller')) const ModalController = asyncComponent(() => import('@/menu/modalconfig/controller')) const StyleCombController = asyncComponent(() => import('@/menu/stylecombcontroller')) const StyleCombControlButton = asyncComponent(() => import('@/menu/stylecombcontrolbutton')) const TableComponent = asyncComponent(() => import('@/templates/sharecomponent/tablecomponent')) sessionStorage.setItem('isEditState', 'true') sessionStorage.setItem('editMenuType', 'menu') // 编辑菜单类型 document.body.className = '' window.GLOB.UserComponentMap = new Map() // 缓存用户自定义组件 class MenuDesign extends Component { state = { dict: localStorage.getItem('lang') !== 'en-US' ? zhCN : enUS, MenuId: '', MenuName: '', MenuNo: '', tableFields: [], delButtons: [], copyButtons: [], thawButtons: [], activeKey: 'basedata', menuloading: false, oriConfig: null, openEdition: '', config: null, popBtn: null, // 弹窗标签页 visible: false, customComponents: [], settingshow: true, controlshow: true, } UNSAFE_componentWillMount() { try { let param = JSON.parse(window.decodeURIComponent(window.atob(this.props.match.params.param))) if (param.type === 'app') { sessionStorage.setItem('appId', param.ID || '') sessionStorage.setItem('lang', param.lang || 'zh-CN') sessionStorage.setItem('kei_no', param.kei_no || '') sessionStorage.setItem('link_type', param.link_type || 'true') sessionStorage.setItem('role_type', param.role_type || 'true') sessionStorage.setItem('login_types', param.login_types || 'true') } else if (param.type === 'view') { this.setState({ MenuId: param.MenuID }) } this.getAppMessage() } catch { notification.warning({ top: 92, message: '菜单信息解析错误!', duration: 5 }) } } shouldComponentUpdate (nextProps, nextState) { return !is(fromJS(this.state), fromJS(nextState)) } componentDidMount () { MKEmitter.addListener('delButtons', this.delButtons) MKEmitter.addListener('thawButtons', this.thawButtons) MKEmitter.addListener('copyButtons', this.copyButtons) MKEmitter.addListener('changePopview', this.initPopview) MKEmitter.addListener('submitComponentStyle', this.updateComponentStyle) MKEmitter.addListener('updateCustomComponent', this.updateCustomComponent) setTimeout(() => { this.updateCustomComponent() this.getAppPictures() }, 1000) } /** * @description 组件销毁,清除state更新 */ componentWillUnmount () { this.setState = () => { return } MKEmitter.removeListener('delButtons', this.delButtons) MKEmitter.removeListener('thawButtons', this.thawButtons) MKEmitter.removeListener('copyButtons', this.copyButtons) MKEmitter.removeListener('changePopview', this.initPopview) MKEmitter.removeListener('submitComponentStyle', this.updateComponentStyle) MKEmitter.removeListener('updateCustomComponent', this.updateCustomComponent) } getAppMessage = () => { Api.getSystemConfig({ func: 's_get_keyids', bid: sessionStorage.getItem('appId') }).then(res => { if (!res) { notification.warning({ top: 92, message: res.message, duration: 5 }) return } let homeId = '' if (this.state.MenuId) { homeId = this.state.MenuId } else { let appViewList = [] if (res.data && res.data.length > 0) { appViewList = res.data appViewList.forEach(item => { if (item.keys_type === 'index') { homeId = item.keys_id } }) } if (!homeId) { homeId = Utils.getuuid() let param = { func: 's_kei_link_keyids_addupt', BID: sessionStorage.getItem('appId'), exec_type: 'y', LText: '' } appViewList.unshift({ appkey: window.GLOB.appkey || '', bid: sessionStorage.getItem('appId') || '', kei_no: sessionStorage.getItem('kei_no') || '', keys_id: homeId, keys_type: 'index', remark: '首页' }) param.LText = appViewList.map(item => `select '${item.keys_id}','${item.keys_type}','${item.kei_no}','${item.appkey}','${item.bid}','${sessionStorage.getItem('CloudUserID')}','${item.remark}'`) param.LText = param.LText.join(' union all ') param.LText = Utils.formatOptions(param.LText) param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss') param.secretkey = Utils.encrypt('', param.timestamp) Api.getSystemConfig(param).then(result => { if (!result.status) { notification.warning({ top: 92, message: result.message, duration: 5 }) } }) } sessionStorage.setItem('appViewList', JSON.stringify(appViewList)) } this.props.history.replace('/pcdesign/' + window.btoa(window.encodeURIComponent(JSON.stringify({MenuID: homeId, type: 'view'})))) this.setState({MenuId: homeId}, () => { this.getMenuParam() }) }) } getAppPictures = () => { Api.getSystemConfig({ func: 's_url_db_adduptdel', PageIndex: 0, // 0 代表全部 PageSize: 0, // 0 代表全部 typecharone: 'image', type: 'search' }).then(res => { if (res.status) { sessionStorage.setItem('app_pictures', JSON.stringify(res.data || [])) } Api.getSystemConfig({ func: 's_url_db_adduptdel', PageIndex: 0, // 0 代表全部 PageSize: 0, // 0 代表全部 typecharone: 'video', type: 'search' }).then(res => { if (res.status) { sessionStorage.setItem('app_videos', JSON.stringify(res.data || [])) } }) }) } updateCustomComponent = () => { Api.getSystemConfig({ func: 's_get_custom_components', typecharone: '' }).then(res => { let coms = [] if (res.cus_list && res.cus_list.length > 0) { res.cus_list.forEach(item => { let config = '' try { config = JSON.parse(window.decodeURIComponent(window.atob(item.long_param))) } catch (e) { console.warn('Parse Failure') config = '' } if (!config || !item.c_name) return window.GLOB.UserComponentMap.set(item.c_id, item.c_name) coms.push({ uuid: item.c_id, type: 'menu', title: item.c_name, url: item.images, component: config.type, subtype: config.subtype, width: config.width || 24, config }) }) } this.setState({customComponents: coms}) this.getRoleFields() }) } updateComponentStyle = (parentId, keys, style) => { const { config } = this.state if (config.uuid !== parentId) return let components = config.components.map(item => { if (keys.includes(item.uuid)) { item.style = {...item.style, ...style} } return item }) this.setState({ config: {...config, components: []} }, () => { this.setState({ config: {...config, components: components} }) }) } delButtons = (items) => { const { copyButtons } = this.state this.setState({ delButtons: [...this.state.delButtons, ...items], copyButtons: copyButtons.filter(item => !items.includes(item.uuid)) }) } copyButtons = (items) => { this.setState({copyButtons: [...this.state.copyButtons, ...items]}) } thawButtons = (item) => { this.setState({thawButtons: [...this.state.thawButtons, item]}) } initPopview = (card, btn) => { // const { oriConfig, config } = this.state // let _config = fromJS(config).toJS() // delete _config.tableFields // if (!is(fromJS(oriConfig), fromJS(_config))) { // notification.warning({ // top: 92, // message: '配置已修改,请保存!', // duration: 5 // }) // return // } // btn.config = _config // btn.component = card // sessionStorage.setItem('editMenuType', 'popview') // 编辑弹窗标签 // this.setState({popBtn: btn, visible: true}) } closeView = () => { const { oriConfig, config } = this.state if (!config) { window.close() return } let _config = fromJS(config).toJS() delete _config.tableFields if (!is(fromJS(oriConfig), fromJS(_config))) { confirm({ title: '配置已修改,放弃保存吗?', content: '', onOk() { window.close() }, onCancel() {} }) } else { window.close() } } getMenuParam = () => { const { MenuId } = this.state let param = { func: 'sPC_Get_LongParam', MenuID: MenuId } Api.getSystemConfig(param).then(result => { if (result.status) { let config = null try { config = result.LongParam ? JSON.parse(window.decodeURIComponent(window.atob(result.LongParam))) : null } catch (e) { console.warn('Parse Failure') config = null } if (!config) { config = { version: 1.0, uuid: MenuId, MenuID: MenuId, Template: 'webPage', easyCode: '', enabled: false, MenuName: '', MenuNo: '', tables: [], components: [], viewType: 'menu', style: { backgroundColor: '#ffffff', backgroundImage: '', paddingLeft: '20px', paddingRight: '20px' } } } config.uuid = MenuId config.MenuID = MenuId this.setState({ oriConfig: config, config: fromJS(config).toJS(), openEdition: result.open_edition || '', }) this.props.modifyCustomMenu(config) } else { notification.warning({ top: 92, message: result.message, duration: 5 }) } }) } getMenuMessage = () => { const { config } = this.state let buttons = [] let _sort = 1 let traversal = (components) => { components.forEach(item => { if (item.type === 'tabs') { item.subtabs.forEach(tab => { traversal(tab.components) }) } else if (item.type === 'group') { traversal(item.components) } else if (item.type === 'card' || (item.type === 'table' && item.subtype === 'tablecard')) { item.action && item.action.forEach(btn => { this.checkBtn(btn) buttons.push(`select '${btn.uuid}' as menuid, '${item.name + '-' + btn.label}' as menuname, '${_sort * 10}' as Sort`) _sort++ }) item.subcards.forEach(card => { card.elements && card.elements.forEach(cell => { if (cell.eleType !== 'button') return this.checkBtn(cell) buttons.push(`select '${cell.uuid}' as menuid, '${item.name + '-' + cell.label}' as menuname, '${_sort * 10}' as Sort`) _sort++ }) card.backElements && card.backElements.forEach(cell => { if (cell.eleType !== 'button') return this.checkBtn(cell) buttons.push(`select '${cell.uuid}' as menuid, '${item.name + '-' + cell.label}' as menuname, '${_sort * 10}' as Sort`) _sort++ }) }) } else if (item.type === 'line' || item.type === 'bar') { item.action && item.action.forEach(btn => { this.checkBtn(btn) buttons.push(`select '${btn.uuid}' as menuid, '${item.name + '-' + btn.label}' as menuname, '${_sort * 10}' as Sort`) _sort++ }) } else if (item.type === 'table' && item.subtype === 'normaltable') { item.action && item.action.forEach(btn => { this.checkBtn(btn) buttons.push(`select '${btn.uuid}' as menuid, '${item.name + '-' + btn.label}' as menuname, '${_sort * 10}' as Sort`) _sort++ }) item.cols && item.cols.forEach(col => { if (col.type !== 'action') return col.elements.forEach(btn => { this.checkBtn(btn) buttons.push(`select '${btn.uuid}' as menuid, '${item.name + '-' + btn.label}' as menuname, '${_sort * 10}' as Sort`) _sort++ }) }) } }) } traversal(config.components) return buttons } checkBtn = (btn) => { if (['prompt', 'exec', 'pop'].includes(btn.OpenType) && btn.Ot === 'required' && btn.verify && btn.verify.scripts && btn.verify.scripts.length > 0) { let hascheck = false btn.verify.scripts.forEach(item => { if (item.status === 'false') return if (/\$check@|@check\$/ig.test(item.sql)) { hascheck = true } }) if (hascheck) { notification.warning({ top: 92, message: `可选择多行的按钮《${btn.label}》中 $check@ 或 @check$ 将不会生效!`, duration: 5 }) } } } filterConfig = (components) => { return components.map(item => { if (item.type === 'tabs') { item.subtabs.forEach(tab => { tab.components = this.filterConfig(tab.components) }) } else if (item.type === 'group') { item.components = this.filterConfig(item.components) } else if (item.type === 'table' && item.subtype === 'normaltable') { item.search = item.search.filter(a => !a.origin) item.action = item.action.filter(a => !a.origin) item.cols = item.cols.filter(a => !a.origin) } return item }) } submitConfig = () => { const { openEdition, delButtons, copyButtons, thawButtons } = this.state let config = fromJS(this.state.config).toJS() if (!config.MenuName || !config.MenuNo || (config.cacheUseful === 'true' && !config.cacheTime)) { notification.warning({ top: 92, message: '请完善菜单基本信息!', duration: 5 }) return } this.setState({ menuloading: true }) setTimeout(() => { config.components = this.filterConfig(config.components) if (config.enabled && this.verifyConfig()) { config.enabled = false } let _config = fromJS(config).toJS() delete _config.tableFields let parMenuId = 'pc' + sessionStorage.getItem('kei_no') + sessionStorage.getItem('lang') let param = { func: 'sPC_TrdMenu_AddUpt', FstID: parMenuId, SndID: parMenuId, ParentID: parMenuId, MenuID: _config.uuid, MenuNo: _config.MenuNo || '', EasyCode: _config.easyCode || '', Template: 'webPage', MenuName: _config.MenuName || '', PageParam: JSON.stringify({Template: 'webPage'}), LongParam: window.btoa(window.encodeURIComponent(JSON.stringify(_config))), LText: '', LTexttb: '' } param.LText = Utils.formatOptions(param.LText) param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss') param.secretkey = Utils.encrypt(param.LText, param.timestamp) if (openEdition) { // 版本管理 param.open_edition = openEdition } let btnParam = { // 添加菜单按钮 func: 'sPC_Button_AddUpt', Type: 40, // 添加菜单下的按钮type为40,按钮下的按钮type为60 ParentID: _config.uuid, MenuNo: _config.MenuNo, Template: 'webPage', PageParam: '', LongParam: '', LText: [] } btnParam.LText = this.getMenuMessage() btnParam.LText = btnParam.LText.join(' union all ') let btnIds = btnParam.LText // 用于复制按钮的过滤 btnParam.LText = Utils.formatOptions(btnParam.LText) btnParam.timestamp = moment().format('YYYY-MM-DD HH:mm:ss') btnParam.secretkey = Utils.encrypt(btnParam.LText, btnParam.timestamp) new Promise(resolve => { // html2canvas(document.getElementById('menu-shell-inner')).then(canvas => { // let _param = { // Base64Img: canvas.toDataURL('image/png') // 获取生成的图片 // } // _param.rduri = options.cloudServiceApi // _param.userid = sessionStorage.getItem('CloudUserID') || '' // _param.LoginUID = sessionStorage.getItem('CloudLoginUID') || '' // Api.fileuploadbase64(_param).then(result => { // if (result.status) { // let Images = Utils.getcloudurl(result.Images) // param.PageParam = JSON.stringify({Template: 'webPage', Images}) // resolve(true) // } else { // notification.warning({ // top: 92, // message: result.ErrMesg, // duration: 5 // }) // resolve(false) // } // }) // }) resolve(true) }).then(res => { // 按钮删除 if (!res) return if (delButtons.length === 0) { return { status: true } } else { let _param = { func: 'sPC_MainMenu_Del', MenuID: delButtons.join(',') } return Api.getSystemConfig(_param) } }).then(res => { // 按钮解除冻结 if (!res) return if (!res.status) { notification.warning({ top: 92, message: res.message, duration: 5 }) return false } let ids = thawButtons.filter(item => btnIds.indexOf(item) !== -1) if (ids.length === 0) { return { status: true } } else { return Api.getSystemConfig({ func: 'sPC_MainMenu_ReDel', MenuID: ids.join(',') }) } }).then(res => { // 页面保存 if (!res) return if (res.status) { return Api.getSystemConfig(param) } else { notification.warning({ top: 92, message: res.message, duration: 5 }) return false } }).then(res => { // 页面按钮关系保存 if (!res) return if (res.status) { this.setState({ oriConfig: fromJS(_config).toJS(), openEdition: res.open_edition || '' }) if (btnParam.LText) { return Api.getSystemConfig(btnParam) } else { return { status: true } } } else { notification.warning({ top: 92, message: res.message, duration: 5 }) return false } }).then(res => { // 按钮复制 if (!res) return if (!res.status) { notification.warning({ top: 92, message: res.message, duration: 5 }) return false } if (copyButtons.length === 0) { return { status: true } } else { return new Promise(resolve => { let deffers = copyButtons.map(item => { return new Promise(resolve => { if (btnIds.indexOf(item.uuid) === -1) { // 复制的按钮已删除 resolve({ status: true }) return } Api.getSystemConfig({ func: 'sPC_Get_LongParam', MenuID: item.$originUuid }).then(result => { if (result.status) { let _conf = '' try { _conf = result.LongParam ? JSON.parse(window.decodeURIComponent(window.atob(result.LongParam))) : '' } catch (e) { console.warn('Parse Failure') _conf = '' } if (_conf) { _conf.components = MenuUtils.resetConfig(_conf.components) _conf.uuid = item.uuid _conf.MenuID = item.uuid _conf.Template = 'webPage' } else { resolve({ status: true }) return } let _param = { func: 'sPC_ButtonParam_AddUpt', ParentID: _config.uuid, MenuID: item.uuid, MenuNo: '', Template: 'webPage', MenuName: item.label, PageParam: JSON.stringify({Template: 'webPage'}), LongParam: window.btoa(window.encodeURIComponent(JSON.stringify(_conf))) } Api.getSystemConfig(_param).then(response => { resolve(response) }) } }) }) }) Promise.all(deffers).then(result => { let error = null result.forEach(response => { if (!response.status) { error = response } }) if (error) { notification.warning({ top: 92, message: error.message, duration: 5 }) resolve(false) } else { resolve({ status: true }) } }) }) } }).then(res => { if (res && res.status) { this.setState({ delButtons: [], copyButtons: [], thawButtons: [], menuloading: false, config: {...config, components: []} }, () => { this.setState({ config: {...this.state.config, components: this.state.oriConfig.components} }) }) notification.success({ top: 92, message: '保存成功', duration: 2 }) } else { this.setState({ menuloading: false }) } }) }, 300) } getRoleFields = () => { Api.getSystemConfig({func: 'sPC_Get_Roles_sModular'}).then(res => { if (res.status) { let _permFuncField = [] let _sysRoles = [] if (res.Roles && res.Roles.length > 0) { _sysRoles = res.Roles.map(role => { return { uuid: Utils.getuuid(), value: role.RoleID, text: role.RoleName } }) } if (res.sModular && res.sModular.length > 0) { res.sModular.forEach(field => { if (field.ModularNo) { _permFuncField.push(field.ModularNo) } }) _permFuncField = _permFuncField.sort() } sessionStorage.setItem('sysRoles', JSON.stringify(_sysRoles)) sessionStorage.setItem('permFuncField', JSON.stringify(_permFuncField)) } }) } onEnabledChange = () => { const { config } = this.state if (!config || (!config.enabled && this.verifyConfig(true))) { return } this.setState({ config: {...config, enabled: !config.enabled} }) } verifyConfig = (show) => { const { config } = this.state let error = '' config.components.forEach(item => { if (error) return if (['propcard', 'brafteditor', 'sandbox'].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.interType && !item.setting.primaryKey) { error = `组件《${item.name}》未设置主键!` } } if (item.type === 'bar' || item.type === 'line' || item.type === 'pie') { if (!item.plot.Xaxis) { error = `组件《${item.name}》图表字段尚未设置!` } } }) if (show && error) { notification.warning({ top: 92, message: error, duration: 5 }) } return error } // 更新配置信息 updateConfig = (config) => { this.setState({ config: config }) this.props.modifyCustomMenu(config) } insert = (item) => { let config = fromJS(this.state.config).toJS() config.components.push(item) this.setState({config}) this.props.modifyCustomMenu(config) } /** * @description 更新常用表信息,快捷添加后更新配置信息 */ updatetable = (config, fields) => { const { tableFields } = this.state config.tableFields = fields ? fields : tableFields this.setState({ tableFields: fields ? fields : tableFields, config }) this.props.modifyCustomMenu(config) } render () { const { activeKey, settingshow, controlshow, dict, MenuId, config, menuloading, customComponents } = this.state return ( <ConfigProvider locale={_locale}> <div className={'mk-pc-view '} id="mk-menu-design-view"> <DndProvider backend={HTML5Backend}> <div className={'menu-setting ' + (!settingshow ? 'hidden' : '')}> <div className="draw"> {settingshow ? <Icon onClick={() => this.setState({settingshow: false})} type="double-left" /> : null} {!settingshow ? <Icon onClick={() => this.setState({settingshow: true})} type="double-right" /> : null} </div> <div className="pc-setting-tools"> <Collapse accordion activeKey={activeKey} bordered={false} onChange={(key) => this.setState({activeKey: key})}> {/* 基本信息 */} <Panel header={dict['mob.basemsg']} key="basedata"> {/* 菜单信息 */} {config ? <MenuForm dict={dict} config={config} MenuId={MenuId} updateConfig={this.updateConfig} /> : null} {/* 表名添加 */} {config ? <TableComponent config={config} updatetable={this.updatetable}/> : null} </Panel> {/* 组件添加 */} <Panel header={dict['mob.component']} key="component"> <SourceWrap MenuType={'pc'} /> </Panel> {customComponents && customComponents.length ? <Panel header="自定义组件" key="cuscomponent"> <SourceWrap components={customComponents} MenuType={'pc'} /> </Panel> : null} <Panel header={'页面背景'} key="background"> {config ? <BgController config={config} updateConfig={this.updateConfig} /> : null} </Panel> <Panel header={'页面内边距'} key="padding"> {config ? <PaddingController config={config} updateConfig={this.updateConfig} /> : null} </Panel> </Collapse> </div> </div> <div className={'menu-control ' + (!controlshow ? 'hidden' : '')}> <div className="draw"> {controlshow ? <Icon onClick={() => this.setState({controlshow: false})} type="double-right" /> : null} {!controlshow ? <Icon onClick={() => this.setState({controlshow: true})} type="double-left" /> : null} </div> <Button type="primary" onClick={this.submitConfig} loading={menuloading}>{dict['mob.save']}</Button> <Switch className="big" checkedChildren={dict['mob.enable']} unCheckedChildren={dict['mob.disable']} checked={config && config.enabled} onChange={this.onEnabledChange} /> <PasteController type="menu" Tab={null} insert={this.insert} /> <StyleCombControlButton menu={config} /> <SysInterface config={config} updateConfig={this.updateConfig}/> <PictureController/> <Button type="default" onClick={this.closeView}>{dict['mob.return']}</Button> </div> <div className={'menu-body ' + (menuloading ? 'saving' : '')}> {config && config.components ? <MenuShell menu={config} handleList={this.updateConfig} /> : null} </div> </DndProvider> <StyleController /> <StyleCombController /> <ModalController /> </div> </ConfigProvider> ) } } const mapStateToProps = () => { return {} } const mapDispatchToProps = (dispatch) => { return { modifyCustomMenu: (customMenu) => dispatch(modifyCustomMenu(customMenu)) } } export default connect(mapStateToProps, mapDispatchToProps)(MenuDesign) src/views/pcdesign/index.scss
New file @@ -0,0 +1,190 @@ .mk-pc-view { background: #000; min-height: 100vh; .menu-setting { position: fixed; left: 0; top: 0px; z-index: 10; transition: left 0.3s; .draw { position: absolute; z-index: 1; background: #ffffff; right: -20px; top: 0px; box-shadow: 0 0 1px #959595; border-radius: 0 2px 2px 0px; i { padding: 12px 3px; } } .pc-setting-tools { height: 100vh; width: 300px; background: #ffffff; box-shadow: 0px 2px 5px #bcbcbc; overflow-y: auto; overflow-x: hidden; > .ant-collapse { background-color: #ffffff; .ant-collapse-item.ant-collapse-item-active { border-bottom: 1px solid #d9d9d9; } .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; } .model-table-tablemanage-view { >.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; min-height: 55px; width: 100%; .anticon { position: absolute; top: 0px; right: 0px; padding: 3px 3px 10px 10px; cursor: pointer; } } } >.tables { width: 66.66666667%!important; } >.ant-form-item-label { width: 33.33333333%; } } } } >.ant-tabs { >.ant-tabs-bar { border-bottom: 1px solid #181F29; margin-bottom: 0px; min-height: 48px; .ant-tabs-tab { padding: 14px 16px; color: rgba(255, 255, 255, 0.85); } .ant-tabs-tab-active.ant-tabs-tab { color: #1890ff; } } } } .pc-setting-tools::-webkit-scrollbar { width: 4px; } .pc-setting-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); } .pc-setting-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); } } .menu-setting.hidden { left: -300px; } .menu-control { position: fixed; right: 0; top: 0px; height: 100vh; padding: 20px 10px; background: #ffffff; z-index: 10; transition: right 0.3s; box-shadow: 0px 0px 5px #bcbcbc; .draw { position: absolute; z-index: 1; background: #ffffff; left: -21px; top: 0px; box-shadow: 0 0 1px #959595; border-radius: 0 2px 2px 0px; i { padding: 12px 3px; } } 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; } } .menu-control.hidden { right: -130px; } .menu-body { width: 100vw; height: 100vh; overflow-x: hidden; position: relative; background: #ffffff; padding: 0px; overflow-y: auto; } .menu-body.saving { .anticon-tool { display: none; } } .menu-body::-webkit-scrollbar { width: 7px; } .menu-body::-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); } .menu-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); } } src/views/pcdesign/menuform/index.jsx
New file @@ -0,0 +1,161 @@ import React, {Component} from 'react' import PropTypes from 'prop-types' import { Form, Row, Col, Input, Radio, Icon, Tooltip, InputNumber } from 'antd' import './index.scss' class CustomMenuForm extends Component { static propTpyes = { dict: PropTypes.object, // 字典项 config: PropTypes.object, MenuId: PropTypes.string, updateConfig: PropTypes.func } state = {} UNSAFE_componentWillMount () { } UNSAFE_componentWillReceiveProps(nextProps) { const { config } = this.props if (!config && nextProps.config) { this.props.form.setFieldsValue({easyCode: nextProps.config.easyCode}) } } // 一二级菜单切换 selectChange = (key, value) => { const { config } = this.props if (key === 'cacheUseful') { this.props.updateConfig({...config, cacheUseful: value}) } else if (key === 'timeUnit') { this.props.updateConfig({...config, timeUnit: value}) } } // 菜单名称 changeName = (e) => { this.props.updateConfig({...this.props.config, MenuName: e.target.value}) } // 菜单参数 changeNo = (e) => { this.props.updateConfig({...this.props.config, MenuNo: e.target.value}) } // 助记码 changeEasyCode = (e) => { this.props.updateConfig({...this.props.config, easyCode: e.target.value}) } changeCacheDay = (val) => { if (typeof(val) !== 'number') { val = '' } this.props.updateConfig({...this.props.config, cacheTime: val}) } render() { const { dict, config } = this.props const { getFieldDecorator } = this.props.form const formItemLayout = { labelCol: { xs: { span: 24 }, sm: { span: 8 } }, wrapperCol: { xs: { span: 24 }, sm: { span: 16 } } } return ( <Form {...formItemLayout} className="custom-menu-form"> <Row> <Col span={24}> <Form.Item label={dict['mob.menu'] + dict['mob.name']}> {getFieldDecorator('MenuName', { initialValue: config.MenuName, rules: [ { required: true, message: dict['mob.required.input'] + dict['mob.menu'] + dict['mob.name'] + '!' } ] })(<Input placeholder="" autoComplete="off" onChange={this.changeName}/>)} </Form.Item> </Col> <Col span={24}> <Form.Item label={dict['mob.menu'] + dict['mob.param']}> {getFieldDecorator('MenuNo', { initialValue: config.MenuNo, rules: [ { required: true, message: dict['mob.required.input'] + dict['mob.menu'] + dict['mob.param'] + '!' } ] })(<Input placeholder="" autoComplete="off" onChange={this.changeNo}/>)} </Form.Item> </Col> <Col span={24}> <Form.Item label={ <Tooltip placement="topLeft" title="对于不经常性变动的信息,缓存数据有助于提高查询效率。"> <Icon type="question-circle" /> 缓存数据 </Tooltip> }> {getFieldDecorator('cacheUseful', { initialValue: config.cacheUseful || 'false' })( <Radio.Group onChange={(e) => {this.selectChange('cacheUseful', e.target.value)}}> <Radio value="true">使用</Radio> <Radio value="false">不使用</Radio> </Radio.Group> )} </Form.Item> </Col> {config.cacheUseful === 'true' ? <Col span={24}> <Form.Item label="单位"> {getFieldDecorator('timeUnit', { initialValue: config.timeUnit || 'day' })( <Radio.Group onChange={(e) => {this.selectChange('timeUnit', e.target.value)}}> <Radio value="day">天</Radio> <Radio value="hour">小时</Radio> </Radio.Group> )} </Form.Item> </Col> : null} {config.cacheUseful === 'true' ? <Col span={24}> <Form.Item label="时长"> {getFieldDecorator('cacheTime', { initialValue: config.cacheTime, rules: [ { required: true, message: dict['mob.required.input'] + '时长!' } ] })( <InputNumber min={1} max={config.timeUnit !== 'hour' ? 7 : 23} precision={0} onChange={this.changeCacheDay}/> )} </Form.Item> </Col> : null} <Col span={24}> <Form.Item label={dict['mob.menu.easycode']}> {getFieldDecorator('easyCode', { initialValue: config.easyCode })(<Input placeholder="" autoComplete="off" onChange={this.changeEasyCode}/>)} </Form.Item> </Col> </Row> </Form> ) } } export default Form.create()(CustomMenuForm) src/views/pcdesign/menuform/index.scss
New file @@ -0,0 +1,10 @@ .custom-menu-form { .anticon-question-circle { color: #c49f47; position: relative; left: -3px; } .ant-input-number { width: 100%; } }