king
2021-02-22 5a7e0659e6365709e2f5c02307d5d5b0a6bd1cc8
2021-02-22
6 文件已重命名
10个文件已修改
8个文件已添加
1703 ■■■■■ 已修改文件
src/api/index.js 14 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/card/cardcellcomponent/index.jsx 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/datasource/verifycard/settingform/index.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/mob/datasource/verifycard/settingform/index.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/mob/header/index.jsx 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pc/bgcontroller/index.jsx 103 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pc/bgcontroller/index.scss 43 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pc/padcontroller/index.jsx 105 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pc/padcontroller/index.scss 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/router/index.js 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/settingcomponent/editTable/index.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/settingcomponent/settingform/datasource/index.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/appmanage/index.jsx 12 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/appmanage/index.scss 补丁 | 查看 | 原始文档 | blame | 历史
src/views/appmanage/mutilform/index.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/appmanage/mutilform/index.scss 补丁 | 查看 | 原始文档 | blame | 历史
src/views/appmanage/submutilform/index.jsx 12 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/appmanage/submutilform/index.scss 补丁 | 查看 | 原始文档 | blame | 历史
src/views/design/header/index.jsx 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mobdesign/index.jsx 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/pcdesign/index.jsx 989 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/pcdesign/index.scss 190 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/pcdesign/menuform/index.jsx 161 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/pcdesign/menuform/index.scss 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
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%;
  }
}