king
2020-08-28 71a0e75ecb56ae643fe1e86188d45f93f48388c9
2020-08-28
42个文件已修改
4个文件已添加
1个文件已删除
2211 ■■■■ 已修改文件
src/api/index.js 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/css/action.scss 32 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/css/main.scss 33 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/sidemenu/index.jsx 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/index.js 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/actioncomponent/actionform/index.jsx 21 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/actioncomponent/dragaction/card.jsx 50 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/actioncomponent/dragaction/index.jsx 15 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/actioncomponent/dragaction/index.scss 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/actioncomponent/formconfig.jsx 400 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/actioncomponent/index.jsx 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/actioncomponent/index.scss 36 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/chart/antv-bar/chartcompile/formconfig.jsx 253 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/chart/antv-bar/chartcompile/index.jsx 534 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/chart/antv-bar/chartcompile/index.scss 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/chart/antv-bar/index.jsx 47 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/chart/antv-bar/index.scss 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/menushell/index.scss 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/searchcomponent/dragsearch/card.jsx 79 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/searchcomponent/dragsearch/index.jsx 46 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/searchcomponent/index.scss 30 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/router/index.js 20 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/store/options.js 7 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/modalconfig/dragelement/card.jsx 42 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/modalconfig/dragelement/index.jsx 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/modalconfig/dragelement/itemtypes.js 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/modalconfig/index.jsx 20 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/modalconfig/index.scss 49 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/actioncomponent/dragaction/card.jsx 37 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/actioncomponent/dragaction/index.scss 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/actioncomponent/index.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/actioncomponent/index.scss 33 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/cardcomponent/index.scss 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/chartgroupcomponent/dragchartview/card.jsx 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/chartgroupcomponent/dragchartview/index.scss 15 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/columncomponent/dragcolumn/card.jsx 51 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/columncomponent/dragcolumn/index.scss 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/columncomponent/index.scss 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/searchcomponent/dragsearch/card.jsx 79 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/searchcomponent/dragsearch/index.scss 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/searchcomponent/index.scss 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/tabscomponent/index.scss 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/tabscomponent/tabdragelement/card.jsx 29 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/tabscomponent/tabdragelement/index.jsx 36 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/tabscomponent/tabdragelement/index.scss 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/login/index.jsx 28 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/menudesign/index.jsx 9 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/index.js
@@ -59,6 +59,11 @@
const setCurrentUrl = () => {
  if (!!(window.history && window.history.pushState)) {
    if (window.location.href.indexOf('paramsmain') > -1) {
      let _href = window.location.href.split('#')
      localStorage.setItem(_href[0] + 'paramsmain', _href[1])
    }
    sessionStorage.clear()
    window.history.replaceState(null, null, window.location.href.split('#')[0] + '#/login')
    window.location.reload()
src/assets/css/action.scss
@@ -126,4 +126,36 @@
    background-color: #e1e5ec;
    border-color: #e1e5ec;
  }
  // 图标颜色
  .mk-icon, .mk-icon:hover, .mk-icon:active, .mk-icon:focus {
    background: transparent;
  }
  .mk-icon.mk-gray {
    color: #666;
  }
  .mk-icon.mk-primary, .mk-icon.mk-border-primary {
    color: #1890ff;
  }
  .mk-icon.mk-default, .mk-icon.mk-dashed {
    color: rgba(0, 0, 0, 0.65);
  }
  .mk-icon.mk-danger, .mk-icon.mk-red, .mk-icon.mk-border-danger {
    color: #ff4d4f;
  }
  .mk-icon.mk-green, .mk-icon.mk-border-green {
    color: #26C281;
  }
  .mk-icon.mk-dgreen, .mk-icon.mk-border-dgreen {
    color: #32c5d2;
  }
  .mk-icon.mk-purple, .mk-icon.mk-border-purple {
    color: #8E44AD;
  }
  .mk-icon.mk-yellow, .mk-icon.mk-border-yellow {
    color: #c49f47;
  }
  .mk-icon.mk-orange, .mk-icon.mk-border-orange {
    color: orange;
  }
}
src/assets/css/main.scss
@@ -202,7 +202,7 @@
}
.ant-popover {
  z-index: 1090!important;
  z-index: 1070!important;
}
.ant-notification-notice.notification-custom-error {
@@ -272,4 +272,35 @@
.ant-drawer {
  z-index: 1080!important;
}
.mk-popover-control-wrap {
  .ant-popover-content {
    position: relative;
    top: 5px;
    .ant-popover-arrow {
      bottom: -3.8px!important;
    }
    .mk-popover-control {
      i {
        padding: 0 5px;
        cursor: pointer;
      }
      .edit {
        color: #1890ff;
      }
      .copy {
        color: #26C281;
      }
      .close {
        color: #ff4d4f;
      }
      .profile {
        color: purple;
      }
    }
    .ant-popover-inner-content {
      padding: 5px 10px;
    }
  }
}
src/components/sidemenu/index.jsx
@@ -70,7 +70,7 @@
      let SubMenuId = sessionStorage.getItem('SubMenu')   // 是否为打开新页面
      let ThirdMenuId = sessionStorage.getItem('ThirdMenu') // 是否为打开新页面
      let msg = sessionStorage.getItem('UserID') + '&ld=' + sessionStorage.getItem('LoginUID') + '&un=' + sessionStorage.getItem('User_Name')
      let msg = sessionStorage.getItem('UserID') + '&ld=' + sessionStorage.getItem('LoginUID') + '&un=' + sessionStorage.getItem('User_Name') + '&mlogo=' + window.GLOB.mainlogo + '&mstyle=' + window.GLOB.style
      let submenuId = '' // 展开二级菜单ID
      let tabId = '' // 打开的tab页id
      
@@ -114,7 +114,7 @@
            }
            // 打开新页面链接
            _tmenu.src = '#/main/' + window.btoa('mm=' + menu.MenuID + '&sm=' + _smenu.MenuID + '&tm=' + child.MenuID + '&ud=' + msg)
            _tmenu.src = '#/paramsmain/' + window.btoa('mm=' + menu.MenuID + '&sm=' + _smenu.MenuID + '&tm=' + child.MenuID + '&ud=' + msg)
            if (child.LinkUrl === 'CommonTable') {
              _tmenu.type = 'CommonTable'
src/index.js
@@ -114,7 +114,9 @@
      }
    }
    let _systemMsg = localStorage.getItem(window.location.href.split('#')[0] + 'system')
    let _href = window.location.href.split('#')[0]
    let _systemMsg = localStorage.getItem(_href + 'system')
    if (_systemMsg) {
      try {
@@ -156,7 +158,7 @@
    if (process.env.NODE_ENV === 'production') { // 用于校验是否存在开发权限
      let _service = window.location.href.replace(/\/index.html(.*)|\/#(.*)/ig, '').replace(new RegExp(document.location.origin + '/?', 'ig'), '')
      GLOB.linkurl = window.location.href.split('#')[0]
      GLOB.linkurl = _href
      if (!/index.html/ig.test(GLOB.linkurl)) {
        GLOB.linkurl = GLOB.linkurl + 'index.html'
      }
@@ -167,12 +169,8 @@
      GLOB.service = 'mkwms/'
    }
    const option = {
      white: 'mk-white'
    }
    if (GLOB.style && option[GLOB.style]) {
      document.getElementById('root').className = option[GLOB.style]
    if (GLOB.style && options.styles[GLOB.style]) {
      document.getElementById('root').className = options.styles[GLOB.style]
    }
    Object.defineProperty(GLOB, 'appId', {
src/menu/actioncomponent/actionform/index.jsx
@@ -73,7 +73,6 @@
    let _menulist = this.props.formlist.filter(form => form.key === 'linkmenu')[0] || ''
    let _opentype = card.OpenType             // 打开方式
    let _tabType = card.tabType || 'SubTable' // 按钮为弹窗(标签)时,标签的类型
    let _options = null                       // 选项列表
    if (card.execMode) {           // 转换打印时打开方式
@@ -83,18 +82,13 @@
      _opentype = 'innerpage'
    }
    let _tabs = this.props.tabs.filter(tab => tab.type === _tabType)
    if (_opentype === 'innerpage') {                                     // 新页面,可选模板(自定义时,可填入外部链接)
      _options = ['label', 'Ot', 'OpenType', 'pageTemplate', 'icon', 'class', 'position']
      if (card.pageTemplate === 'custom') {
        _options.push('url', 'joint')
      }
    } else if (_opentype === 'blank' || _opentype === 'tab') {           // 新标签或当前页面替换
      _options = ['label', 'Ot', 'OpenType', 'icon', 'class', 'position', 'tabTemplate']
      if (card.tabTemplate === 'ThdMenu') {
        _options.push('linkmenu')
      }
      _options = ['label', 'Ot', 'OpenType', 'icon', 'class', 'position', 'tabTemplate', 'linkmenu']
    } else if (_opentype === 'popview') {                                // 模态框标签页
      _options = ['label', 'Ot', 'OpenType', 'icon', 'class', 'position', 'tabType', 'linkTab', 'popClose']
    } else if (_opentype === 'excelOut') {    // 导入导出
@@ -161,7 +155,7 @@
              value: '',
              text: '新建'
            },
            ..._tabs
            ...this.props.tabs
          ]
        } else if (item.key === 'OpenType') {
          item.initVal = _opentype
@@ -203,10 +197,7 @@
          _options.push('url', 'joint')
        }
      } else if (value === 'blank' || value === 'tab') {
        _options = ['label', 'Ot', 'OpenType', 'icon', 'class', 'position', 'tabTemplate']
        if (card.tabTemplate === 'ThdMenu') {
          _options.push('linkmenu')
        }
        _options = ['label', 'Ot', 'OpenType', 'icon', 'class', 'position', 'tabTemplate', 'linkmenu']
      } else if (value === 'popview') {
        _options = ['label', 'Ot', 'OpenType', 'icon', 'class', 'position', 'tabType', 'linkTab', 'popClose']
      } else if (value === 'excelOut') {
@@ -424,11 +415,7 @@
        this.props.form.setFieldsValue(_fieldval)
      })
    } else if (key === 'tabTemplate') {
      let _options = ['label', 'Ot', 'OpenType', 'icon', 'class', 'position', 'tabTemplate']
      if (value === 'ThdMenu') {
        _options.push('linkmenu')
      }
      let _options = ['label', 'Ot', 'OpenType', 'icon', 'class', 'position', 'tabTemplate', 'linkmenu']
      this.setState({
        openType: value,
src/menu/actioncomponent/dragaction/card.jsx
@@ -1,9 +1,9 @@
import React from 'react'
import { useDrag, useDrop } from 'react-dnd'
import { Icon, Button } from 'antd'
import { Icon, Button, Popover } from 'antd'
import './index.scss'
const Card = ({ id, card, moveCard, findCard, editCard, delCard, copyCard, profileCard, doubleClickCard }) => {
const Card = ({ id, cardIds, type, card, moveCard, findCard, editCard, delCard, copyCard, profileCard, doubleClickCard }) => {
  const originalIndex = findCard(id).index
  const [{ isDragging }, drag] = useDrag({
    item: { type: 'action', id, originalIndex },
@@ -17,6 +17,8 @@
    drop: () => {},
    hover({ id: draggedId }) {
      if (!draggedId) return
      if (!cardIds.includes(draggedId)) return
      if (draggedId !== id) {
        const { index: overIndex } = findCard(id)
        moveCard(draggedId, overIndex)
@@ -34,23 +36,37 @@
    hasProfile = true
  }
  let btnElement = null
  if (type === 'chart') {
    btnElement = (<Icon type={card.icon} className={'mk-icon mk-' + card.class} onClick={() => editCard(id)} />)
  } else {
    btnElement = (
      <Button
        className={'mk-btn mk-' + card.class}
        icon={card.icon}
        key={card.uuid}
        onDoubleClick={() => doubleClickCard(id)}
      >
        {card.label}
      </Button>
    )
  }
  return (
    <div className="page-card" style={{ opacity: opacity}}>
      <div ref={node => drag(drop(node))}>
        <Button
          className={'mk-btn mk-' + card.class}
          icon={card.icon}
          key={card.uuid}
          onDoubleClick={() => doubleClickCard(id)}
        >
          {card.label}{card.position === 'grid' && <Icon type="table" />}
        </Button>
    <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={
      <div className="mk-popover-control">
        <Icon className="edit" title="edit" type="edit" onClick={() => editCard(id)} />
        <Icon className="copy" title="copy" type="copy" onClick={() => copyCard(id)} />
        <Icon className="close" title="close" type="close" onClick={() => delCard(id)} />
        {hasProfile ? <Icon className="profile" title="setting" type="profile" onClick={() => profileCard(id)} /> : null}
      </div>
      <Icon className="edit" title="edit" type="edit" onClick={() => editCard(id)} />
      <Icon className="edit copy" title="copy" type="copy" onClick={() => copyCard(id)} />
      <Icon className="edit close" title="close" type="close" onClick={() => delCard(id)} />
      {hasProfile ? <Icon className="edit profile" title="setting" type="profile" onClick={() => profileCard(id)} /> : null}
    </div>
    } trigger="hover">
      <div className="page-card" style={{ opacity: opacity}}>
        <div ref={node => drag(drop(node))}>
          {btnElement}
        </div>
      </div>
    </Popover>
  )
}
export default Card
src/menu/actioncomponent/dragaction/index.jsx
@@ -8,7 +8,7 @@
import Card from './card'
import './index.scss'
const Container = ({list, handleList, handleMenu, deleteMenu, profileMenu, doubleClickCard }) => {
const Container = ({type, list, handleList, handleMenu, deleteMenu, profileMenu, doubleClickCard }) => {
  const [cards, setCards] = useState(list)
  const moveCard = (id, atIndex) => {
    const { card, index } = findCard(id)
@@ -90,13 +90,11 @@
    handleList(_cards, copycard)
  }
  let cardIds = cards.map(card => card.uuid)
  const [, drop] = useDrop({
    accept: 'action',
    drop(item) {
      if (item.hasOwnProperty('originalIndex')) {
        return
      }
    }
    drop() {}
  })
  const addaction = () => {
@@ -107,8 +105,7 @@
    newcard.label = 'button'
    newcard.sqlType = ''
    newcard.Ot = 'requiredSgl'
    newcard.OpenType = 'excelIn'
    newcard.tabType = 'SubTable'
    newcard.OpenType = 'prompt'
    newcard.icon = ''
    newcard.class = 'default'
    newcard.intertype = 'inner'
@@ -138,6 +135,8 @@
        <Card
          id={card.uuid}
          key={card.uuid}
          cardIds={cardIds}
          type={type}
          card={card}
          moveCard={moveCard}
          copyCard={copyCard}
src/menu/actioncomponent/dragaction/index.scss
@@ -1,6 +0,0 @@
.common-drawarea-placeholder {
  width: 100%;
  line-height: 65px;
  text-align: center;
  color: #bcbcbc;
}
src/menu/actioncomponent/formconfig.jsx
New file
@@ -0,0 +1,400 @@
import zhCN from '@/locales/zh-CN/model.js'
import enUS from '@/locales/en-US/model.js'
const Formdict = localStorage.getItem('lang') !== 'en-US' ? zhCN : enUS
/**
 * @description 获取按钮表单配置信息
 * @param {*} card           编辑按钮
 * @param {*} functip        生成存储过程提示
 * @param {*} setting        组件配置
 * @param {*} permFuncField  存储过程可用的开始字段
 * @param {*} type           按钮类型,用于区分可选的打开方式
 */
export function getActionForm (card, functip, setting, permFuncField = [], type, menulist = []) {
  let opentypes = [
    {
      value: 'pop',
      text: Formdict['model.form.popform']
    }, {
      value: 'prompt',
      text: Formdict['model.form.prompt']
    }, {
      value: 'exec',
      text: Formdict['model.form.exec']
    }, {
      value: 'excelIn',
      text: Formdict['model.form.excelIn']
    }, {
      value: 'excelOut',
      text: Formdict['model.form.excelOut']
    }, {
      value: 'popview',
      text: Formdict['model.form.popview']
    }, {
      value: 'tab',
      text: Formdict['model.form.tab']
    }, {
      value: 'innerpage',
      text: Formdict['model.form.newpage']
    }, {
      value: 'funcbutton',
      text: Formdict['model.form.funcbutton']
    }
  ]
  if (type === 'chart') {
    if (card.focus) {
      // 导入和导出excel,按钮名称直接为导入、导出
      card.label = '导出Excel'
      card.OpenType = 'excelOut'
      card.icon = 'download'
      card.intertype = setting.interType
      card.innerFunc = setting.innerFunc
      card.sysInterface = setting.sysInterface
      card.outerFunc = setting.outerFunc
      card.interface = setting.interface
      card.class = 'dgreen'
    }
    opentypes = [
      {
        value: 'excelIn',
        text: Formdict['model.form.excelIn']
      }, {
        value: 'excelOut',
        text: Formdict['model.form.excelOut']
      }
    ]
  }
  let forms = [
    {
      type: 'select',
      key: 'OpenType',
      label: Formdict['header.form.openType'],
      initVal: card.OpenType,
      required: true,
      options: opentypes
    },
    {
      type: 'select',
      key: 'funcType',
      label: Formdict['header.form.funcType'],
      initVal: card.funcType || '',
      required: true,
      options: [{
        value: 'changeuser',
        text: Formdict['header.form.func.changeuser']
      }, {
        value: 'print',
        text: Formdict['header.form.func.print']
      }]
    },
    {
      type: 'select',
      key: 'execMode',
      label: Formdict['model.form.execMode'],
      initVal: card.execMode || 'exec',
      required: true,
      options: [{
        value: 'exec',
        text: Formdict['model.form.exec']
      }, {
        value: 'prompt',
        text: Formdict['model.form.prompt']
      }, {
        value: 'pop',
        text: Formdict['model.form.popform']
      }]
    },
    {
      type: 'radio',
      key: 'intertype',
      label: Formdict['header.form.intertype'],
      initVal: card.intertype || 'inner',
      required: true,
      options: [{
        value: 'inner',
        text: Formdict['header.form.interface.inner']
      }, {
        value: 'outer',
        text: Formdict['header.form.interface.outer']
      }]
    },
    {
      type: 'select',
      key: 'sqlType',
      label: Formdict['header.form.action.type'],
      initVal: card.sqlType || '',
      tooltip: Formdict['header.form.actionhelp.sqlType'],
      required: false,
      options: []
    },
    {
      type: 'text',
      key: 'label',
      label: '按钮名称',
      initVal: card.label,
      required: true,
      readonly: false
    },
    {
      type: 'text',
      key: 'sql',
      label: Formdict['model.form.tablename'],
      initVal: card.sql || setting.tableName || '',
      tooltip: Formdict['header.form.actionhelp.tablename'],
      required: false
    },
    {
      type: 'text',
      key: 'innerFunc',
      label: Formdict['header.form.innerFunc'],
      initVal: card.innerFunc || '',
      tooltip: functip,
      fields: permFuncField,
      tooltipClass: 'middle',
      required: false,
      readonly: false
    },
    {
      type: 'select',
      key: 'linkTab',
      label: '关联标签',
      initVal: card.linkTab || '',
      required: false,
      options: []
    },
    {
      type: 'select',
      key: 'pageTemplate',
      label: Formdict['model.form.newpage.type'],
      initVal: card.pageTemplate || '',
      required: true,
      options: [{
        value: 'print',
        text: Formdict['header.menu.printTemplate']
      }, {
        value: 'pay',
        text: Formdict['model.pay']
      }, {
        value: 'custom',
        text: Formdict['header.form.custom']
      }]
    },
    {
      type: 'text',
      key: 'url',
      label: Formdict['model.form.newpage.url'],
      initVal: card.url || '',
      required: true
    },
    {
      type: 'radio',
      key: 'sysInterface',
      label: Formdict['header.form.sysInterface'],
      initVal: card.sysInterface || 'false',
      required: true,
      options: [{
        value: 'true',
        text: Formdict['model.true']
      }, {
        value: 'false',
        text: Formdict['model.false']
      }]
    },
    {
      type: 'text',
      key: 'outerFunc',
      label: Formdict['header.form.outerFunc'],
      initVal: card.outerFunc || '',
      required: false,
      readonly: false
    },
    {
      type: 'text',
      key: 'interface',
      label: Formdict['header.form.interface'],
      initVal: card.sysInterface === 'true' ? (window.GLOB.mainSystemApi || '') : (card.interface || ''),
      required: true,
      readonly: card.sysInterface === 'true'
    },
    {
      type: 'text',
      key: 'callbackFunc',
      label: Formdict['header.form.callbackFunc'],
      initVal: card.callbackFunc || '',
      required: false,
      readonly: false
    },
    {
      type: 'select',
      key: 'position',
      label: Formdict['header.form.position'],
      initVal: card.position || 'toolbar',
      required: true,
      options: [{
        value: 'toolbar',
        text: Formdict['header.form.toolbar']
      }, {
        value: 'grid',
        text: Formdict['header.form.grid']
      }]
    },
    {
      type: 'select',
      key: 'Ot',
      label: Formdict['header.form.isRequired'],
      initVal: card.Ot || 'requiredSgl',
      required: true,
      options: []
    },
    {
      type: 'cascader',
      key: 'linkmenu',
      label: Formdict['model.form.linkmenu'],
      initVal: card.linkmenu || [],
      required: true,
      options: menulist
    },
    {
      type: 'radio',
      key: 'afterExecSuccess',
      label: Formdict['header.form.afterExecSuccess'],
      initVal: card.afterExecSuccess || 'close',
      required: true,
      options: [{
        value: 'close',
        text: Formdict['model.close']
      }, {
        value: 'notclose',
        text: Formdict['model.notclose']
      }]
    },
    {
      type: 'radio',
      key: 'afterExecError',
      label: Formdict['header.form.afterExecError'],
      initVal: card.afterExecError || 'notclose',
      required: true,
      options: [{
        value: 'close',
        text: Formdict['model.close']
      }, {
        value: 'notclose',
        text: Formdict['model.notclose']
      }]
    },
    {
      type: 'radio',
      key: 'execSuccess',
      label: Formdict['model.form.afterSuccess'],
      initVal: card.execSuccess || 'never',
      required: true,
      options: [{
        value: 'grid',
        text: Formdict['header.form.refresh']
      }, {
        value: 'never',
        text: Formdict['header.form.refresh.never']
      }]
    },
    {
      type: 'radio',
      key: 'execError',
      label: Formdict['model.form.afterError'],
      initVal: card.execError || 'never',
      required: true,
      options: [{
        value: 'grid',
        text: Formdict['header.form.refresh']
      }, {
        value: 'never',
        text: Formdict['header.form.refresh.never']
      }]
    },
    {
      type: 'radio',
      key: 'popClose',
      label: Formdict['header.form.popClose'],
      initVal: card.popClose || 'never',
      required: true,
      options: [{
        value: 'grid',
        text: Formdict['header.form.refresh']
      }, {
        value: 'never',
        text: Formdict['header.form.refresh.never']
      }]
    },
    {
      type: 'select',
      key: 'icon',
      label: Formdict['model.icon'],
      initVal: card.icon,
      required: type === 'chart', // 图表必须使用图标
      options: []
    },
    {
      type: 'select',
      key: 'class',
      label: Formdict['model.form.color'],
      initVal: card.class,
      required: false,
      options: []
    },
    {
      type: 'radio',
      key: 'joint',
      label: Formdict['model.form.paramJoint'],
      initVal: card.joint || 'true',
      required: false,
      options: [{
        value: 'true',
        text: Formdict['model.true']
      }, {
        value: 'false',
        text: Formdict['model.false']
      }]
    },
    {
      type: 'text',
      key: 'sheet',
      label: Formdict['model.form.tablename'],
      initVal: card.sheet || setting.tableName || '',
      required: true
    },
    {
      type: 'radio',
      key: 'pagination',
      label: Formdict['header.form.pagination'],
      initVal: card.pagination || 'false',
      required: false,
      options: [{
        value: 'true',
        text: Formdict['model.true']
      }, {
        value: 'false',
        text: Formdict['model.false']
      }]
    },
    {
      type: 'radio',
      key: 'search',
      label: '搜索条件',
      initVal: card.search || 'false',
      required: false,
      options: [{
        value: 'true',
        text: '必填'
      }, {
        value: 'false',
        text: '非必填'
      }]
    }
  ]
  if (type === 'chart') {
    return forms
  }
}
src/menu/actioncomponent/index.jsx
@@ -10,7 +10,7 @@
import DevUtils from '@/utils/devutils.js'
import zhCN from '@/locales/zh-CN/model.js'
import enUS from '@/locales/en-US/model.js'
import { getActionForm } from '@/templates/zshare/formconfig'
import { getActionForm } from './formconfig'
import ActionForm from './actionform'
import VerifyCard from '@/templates/zshare/verifycard'
@@ -85,7 +85,9 @@
   */
  handleAction = (card) => {
    const { menu } = this.props
    let ableField = this.props.usefulFields.join(', ')
    const { config } = this.props
    let ableField = menu.permFuncField ? menu.permFuncField.join(', ') : ''
    let functip = <div>
      <p style={{marginBottom: '5px'}}>{this.state.dict['model.tooltip.func.innerface'].replace('@ableField', ableField)}</p>
      <p>{this.state.dict['model.tooltip.func.outface']}</p>
@@ -149,14 +151,14 @@
        this.setState({
          visible: true,
          card: card,
          formlist: getActionForm(card, functip, this.props.config, this.props.usefulFields, this.props.type, menulist)
          formlist: getActionForm(card, functip, config.setting, menu.permFuncField, this.props.type, menulist)
        })
      })
    } else {
      this.setState({
        visible: true,
        card: card,
        formlist: getActionForm(card, functip, this.props.config, this.props.usefulFields, this.props.type, menulist)
        formlist: getActionForm(card, functip, config.setting, menu.permFuncField, this.props.type, menulist)
      })
    }
  }
@@ -875,12 +877,13 @@
  }
  render() {
    const { config } = this.props
    const { config, type } = this.props
    const { actionlist, visible, card, dict, copying, profVisible } = this.state
    return (
      <div className="model-custom-chart-action-list">
        <DragElement
          type={type}
          list={actionlist}
          setting={this.props.config.setting}
          handleList={this.handleList}
src/menu/actioncomponent/index.scss
@@ -1,8 +1,4 @@
.model-custom-chart-action-list {
  position: absolute;
  right: 0px;
  z-index: 4;
  .anticon-question-circle {
    color: #c49f47;
    position: absolute;
@@ -12,39 +8,16 @@
  .ant-row .anticon-plus {
    color: #26C281;
    float: right;
    padding: 5px;
    margin-top: 20px;
  }
  .page-card {
    margin: 0px 0px 0px 0px;
    padding: 15px 10px 0 0;
    margin: 0px;
    padding: 0px 5px;
    position: relative;
    float: right;
    div {
      cursor: move;
    }
    .edit {
      position: absolute;
      left: 0;
      top: 0px;
      color: #1890ff;
      cursor: pointer;
      display: none;
    }
    .edit.copy {
      left: 20px;
      color: #26C281;
    }
    .edit.close {
      left: 40px;
      color: #ff4d4f;
    }
    .edit.profile {
      left: 60px;
      color: purple;
    }
    button {
      min-width: 65px;
@@ -55,11 +28,6 @@
        right: 1px;
        bottom: 0px;
      }
    }
  }
  .page-card:hover {
    .edit {
      display: inline-block;
    }
  }
}
src/menu/components/chart/antv-bar/chartcompile/formconfig.jsx
New file
@@ -0,0 +1,253 @@
import zhCN from '@/locales/zh-CN/model.js'
import enUS from '@/locales/en-US/model.js'
const Formdict = localStorage.getItem('lang') !== 'en-US' ? zhCN : enUS
/**
 * @description 获取图表视图配置表单
 * @param {object} card       // 图表对象
 * @param {Array}  columns    // 显示列
 */
export function getBarOrLineChartOptionForm (card, columns) {
  let shapes = []
  if (card.chartType === 'line') {
    shapes = [
      { field: 'smooth', label: 'smooth' },
      { field: 'line', label: 'line' },
      { field: 'dot', label: 'dot' },
      { field: 'dash', label: 'dash' },
      { field: 'hv', label: 'hv' },
      { field: 'vh', label: 'vh' },
      { field: 'hvh', label: 'hvh' },
      { field: 'vhv', label: 'vhv' }
    ]
  } else if (card.chartType === 'bar') {
    shapes = [
      { field: 'rect', label: 'rect' },
      { field: 'hollow-rect', label: 'hollow-rect' },
      { field: 'line', label: 'line' },
      { field: 'tick', label: 'tick' },
      { field: 'funnel', label: 'funnel' },
      { field: 'pyramid', label: 'pyramid' }
    ]
  }
  return [
    {
      type: 'radio',
      key: 'datatype',
      label: '数据类型',
      initVal: card.datatype || 'query',
      tooltip: '统计图表适用于表格不分页,且数据需要转换',
      required: false,
      options: [
        { value: 'query', text: Formdict['header.form.query'] },
        { value: 'statistics', text: Formdict['header.form.statistics'] }
      ]
    },
    {
      type: 'select',
      key: 'Xaxis',
      label: 'X-轴',
      initVal: card.Xaxis || '',
      required: true,
      options: columns.filter(col => col.type === 'text')
    },
    {
      type: 'select',
      key: 'Yaxis',
      label: 'Y-轴',
      initVal: card.Yaxis || [],
      multi: true, // 多选
      hidden: card.datatype === 'statistics',
      required: true,
      options: columns.filter(col => col.type === 'number')
    },
    {
      type: 'select',
      key: 'InfoType',
      label: '类型',
      initVal: card.InfoType || '',
      hidden: card.datatype !== 'statistics',
      required: true,
      options: columns.filter(col => col.type === 'text')
    },
    {
      type: 'select',
      key: 'InfoValue',
      label: '值',
      initVal: card.InfoValue || '',
      hidden: card.datatype !== 'statistics',
      required: true,
      options: columns.filter(col => col.type === 'number')
    },
    {
      type: 'select',
      key: 'legend',
      label: '图例位置',
      initVal: card.legend || 'bottom',
      required: false,
      options: [
        { field: 'top', label: 'top' },
        { field: 'top-left', label: 'top-left' },
        { field: 'top-right', label: 'top-right' },
        { field: 'right', label: 'right' },
        { field: 'right-top', label: 'right-top' },
        { field: 'right-bottom', label: 'right-bottom' },
        { field: 'left', label: 'left' },
        { field: 'left-top', label: 'left-top' },
        { field: 'left-bottom', label: 'left-bottom' },
        { field: 'bottom', label: 'bottom' },
        { field: 'bottom-left', label: 'bottom-left' },
        { field: 'bottom-right', label: 'bottom-right' },
        { field: 'hidden', label: 'hidden' }
      ]
    },
    {
      type: 'select',
      key: 'shape',
      label: '形状',
      initVal: card.shape || (shapes[0] && shapes[0].field),
      required: false,
      options: shapes
    },
    {
      type: 'radio',
      key: 'tooltip',
      label: '提示信息',
      initVal: card.tooltip || 'true',
      required: false,
      options: [{
        value: 'true',
        text: '显示'
      }, {
        value: 'false',
        text: '隐藏'
      }]
    },
    {
      type: 'radio',
      key: 'coordinate',
      label: '坐标',
      initVal: card.coordinate || 'angle',
      required: false,
      options: [{
        value: 'angle',
        text: '二维坐标'
      }, {
        value: 'polar',
        text: '极坐标'
      }]
    },
    {
      type: 'radio',
      key: 'point',
      label: '点图',
      initVal: card.point || 'false',
      required: false,
      forbid: !['line'].includes(card.chartType),
      options: [{
        value: 'true',
        text: '显示'
      }, {
        value: 'false',
        text: '隐藏'
      }]
    },
    {
      type: 'radio',
      key: 'transpose',
      label: '变换',
      initVal: card.transpose || 'false',
      required: false,
      options: [{
        value: 'true',
        text: Formdict['model.true']
      }, {
        value: 'false',
        text: Formdict['model.false']
      }]
    },
    {
      type: 'radio',
      key: 'show',
      label: '显示值',
      initVal: card.show || 'value',
      required: false,
      options: [{
        value: 'percent',
        text: '百分比'
      }, {
        value: 'value',
        text: '数值'
      }]
    },
    {
      type: 'radio',
      key: 'label',
      label: '标注-值',
      initVal: card.label || 'false',
      required: false,
      options: [{
        value: 'true',
        text: '显示'
      }, {
        value: 'false',
        text: '隐藏'
      }]
    }, {
      type: 'radio',
      key: 'adjust',
      label: '多柱排列',
      initVal: card.adjust || 'dodge',
      required: false,
      forbid: !['bar'].includes(card.chartType),
      options: [{
        value: 'dodge',
        text: '分组'
      }, {
        value: 'stack',
        text: '堆叠'
      }]
    }, {
      type: 'radio',
      key: 'repeat',
      label: '重复数据',
      initVal: card.repeat || 'unrepeat',
      required: false,
      options: [{
        value: 'unrepeat',
        text: '去重'
      }, {
        value: 'average',
        text: '平均'
      }, {
        value: 'cumsum',
        text: '累加'
      }]
    }, {
      type: 'number',
      key: 'InfoDefNumber',
      label: '展示数',
      tooltip: '默认显示类型数量',
      min: 1,
      max: 50,
      decimal: 0,
      initVal: card.InfoDefNumber || 5,
      hidden: card.datatype !== 'statistics',
      required: true
    }, {
      type: 'number',
      key: 'correction',
      label: '数据修正',
      tooltip: '当数据项少于设置值时,系统会自动修正(避免柱形图过宽),在自定义中,设置为折线图时失效。',
      min: 5,
      max: 30,
      decimal: 0,
      initVal: card.correction,
      forbid: !['bar'].includes(card.chartType),
      required: false
    }
  ]
}
src/menu/components/chart/antv-bar/chartcompile/index.jsx
New file
@@ -0,0 +1,534 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import { fromJS } from 'immutable'
import { Modal, Form, Row, Col, Select, Icon, Radio, Tooltip, Input, InputNumber, Cascader, Tabs } from 'antd'
import { getBarOrLineChartOptionForm } from './formconfig'
import { minkeColorSystem, colorTransform } from '@/utils/option.js'
import './index.scss'
const { TabPane } = Tabs
class LineChartDrawerForm extends Component {
  static propTpyes = {
    dict: PropTypes.object,
    plot: PropTypes.object,
    config: PropTypes.object,
    plotchange: PropTypes.func
  }
  state = {
    view: 'normal',
    visible: false,
    disabled: true,
    plot: null,
    formlist: null,
    datatype: null,
    fieldName: null,
    colorOptions: fromJS(minkeColorSystem).toJS().map(option => {
      option.children = option.children.map(cell => {
        let _cell = {}
        _cell.label = <div className={'background ' + cell.value}>{cell.value}</div>
        _cell.value = colorTransform[cell.value]
        return _cell
      })
      return option
    }),
    shapeOptions: [
      {
        value: 'line',
        label: '折线',
        children: [
          { value: 'smooth', label: 'smooth' },
          { value: 'line', label: 'line' },
          { value: 'dot', label: 'dot' },
          { value: 'dash', label: 'dash' },
          { value: 'hv', label: 'hv' },
          { value: 'vh', label: 'vh' },
          { value: 'hvh', label: 'hvh' },
          { value: 'vhv', label: 'vhv' }
        ]
      },
      {
        value: 'bar',
        label: '柱形',
        children: [
          { value: 'rect', label: 'rect' },
          { value: 'hollow-rect', label: 'hollow-rect' },
          { value: 'line', label: 'line' },
          { value: 'tick', label: 'tick' },
          { value: 'funnel', label: 'funnel' },
          { value: 'pyramid', label: 'pyramid' }
        ],
      }
    ]
  }
  showDrawer = () => {
    const { config } = this.props
    let fieldName = {}
    config.columns.forEach(col => {
      if (col.field) {
        fieldName[col.field] = col.label
      }
    })
    this.setState({
      visible: true,
      view: 'normal',
      fieldName: fieldName,
      plot: fromJS(config.plot).toJS(),
      formlist: getBarOrLineChartOptionForm(config.plot, config.columns, config.setting)
    })
  }
  radioChange = (e, key) => {
    const { formlist } = this.state
    let val = e.target.value
    if (key === 'datatype') {
      this.setState({
        datatype: val,
        formlist: formlist.map(item => {
          if (['Yaxis'].includes(item.key)) {
            item.hidden = val === 'statistics'
          } else if (['InfoType', 'InfoValue', 'InfoDefNumber'].includes(item.key)) {
            item.hidden = val !== 'statistics'
          }
          return item
        })
      })
    }
  }
  getFields() {
    const { formlist } = this.state
    const { getFieldDecorator } = this.props.form
    const fields = []
    if (!formlist) {
      return fields
    }
    formlist.forEach((item, index) => {
      if (item.hidden || item.forbid) return
      if (item.type === 'text') {
        fields.push(
          <Col span={12} key={index}>
            <Form.Item label={item.tooltip ?
              <Tooltip placement="topLeft" title={item.tooltip}>
                <Icon type="question-circle" />
                {item.label}
              </Tooltip> : item.label
            }>
              {getFieldDecorator(item.key, {
                initialValue: item.initVal,
                rules: [
                  {
                    required: !!item.required,
                    message: this.props.dict['form.required.input'] + item.label + '!'
                  }
                ]
              })(<Input placeholder="" autoComplete="off" disabled={item.readonly}/>)}
            </Form.Item>
          </Col>
        )
      } else if (item.type === 'number') {
        fields.push(
          <Col span={12} key={index}>
            <Form.Item label={item.tooltip ?
              <Tooltip placement="topLeft" title={item.tooltip}>
                <Icon type="question-circle" />
                {item.label}
              </Tooltip> : item.label
            }>
              {getFieldDecorator(item.key, {
                initialValue: item.initVal,
                rules: [
                  {
                    required: !!item.required,
                    message: this.props.dict['form.required.input'] + item.label + '!'
                  }
                ]
              })(<InputNumber min={item.min} max={item.max} precision={item.decimal} />)}
            </Form.Item>
          </Col>
        )
      } else if (item.type === 'select') { // 下拉
        fields.push(
          <Col span={12} key={index}>
            <Form.Item label={item.tooltip ?
              <Tooltip placement="topLeft" title={item.tooltip}>
                <Icon type="question-circle" />
                {item.label}
              </Tooltip> : item.label
            }>
              {getFieldDecorator(item.key, {
                initialValue: item.initVal,
                rules: [
                  {
                    required: !!item.required,
                    message: this.props.dict['form.required.select'] + item.label + '!'
                  }
                ]
              })(
                <Select mode={item.multi ? 'multiple' : ''}>
                  {item.options.map((option, index) =>
                    <Select.Option key={index} value={option.field}>
                      {option.label}
                    </Select.Option>
                  )}
                </Select>
              )}
            </Form.Item>
          </Col>
        )
      } else if (item.type === 'radio') {
        fields.push(
          <Col span={12} key={index}>
            <Form.Item label={item.tooltip ?
              <Tooltip placement="topLeft" title={item.tooltip}>
                <Icon type="question-circle" />
                {item.label}
              </Tooltip> : item.label
            }>
              {getFieldDecorator(item.key, {
                initialValue: item.initVal,
                rules: [
                  {
                    required: !!item.required,
                    message: this.props.dict['form.required.select'] + item.label + '!'
                  }
                ]
              })(
                <Radio.Group disabled={item.readonly} onChange={(e) => this.radioChange(e, item.key)}>
                  {item.options.map(option => {
                    return (
                      <Radio key={option.value} value={option.value}>{option.text}</Radio>
                    )
                  })}
                </Radio.Group>
              )}
            </Form.Item>
          </Col>
        )
      }
    })
    return fields
  }
  getCustomFields = () => {
    const { getFieldDecorator } = this.props.form
    const { plot, fieldName, enabled, colorOptions, shapeOptions } = this.state
    const fields = []
    if (!plot.customs) return null
    fields.push(<Col span={12} key="enabled">
      <Form.Item label="是否启用" style={{marginBottom: 10}}>
        {getFieldDecorator('enabled', {
          initialValue: plot.enabled || 'false'
        })(
          <Radio.Group onChange={this.enabledChange}>
            <Radio value="true">是</Radio>
            <Radio value="false">否</Radio>
          </Radio.Group>
        )}
      </Form.Item>
    </Col>)
    plot.customs.forEach((item, i) => {
      fields.push(<Col span={24} key={'field' + i}>
        <p className="field-title">{fieldName[item.field]}</p>
      </Col>)
      fields.push(<Col span={12} key={'shape' + i}>
        <Form.Item label="形状">
          {getFieldDecorator(item.field + '$shape', {
            initialValue: item.$shape,
            rules: [
              {
                required: enabled === 'true',
                message: this.props.dict['form.required.select'] + '形状!'
              }
            ]
          })(
            <Cascader
              disabled={enabled === 'false'}
              options={shapeOptions}
              placeholder=""
              displayRender={(label, selectedOptions) => selectedOptions[0] ? selectedOptions[0].label + ' / ' + selectedOptions[1].value : ''}
            />
          )}
        </Form.Item>
      </Col>)
      fields.push(<Col span={12} key={'color' + i}>
        <Form.Item label="颜色">
          {getFieldDecorator(item.field + '$color', {
            initialValue: item.$color,
            rules: [
              {
                required: enabled === 'true',
                message: this.props.dict['form.required.select'] + '颜色!'
              }
            ]
          })(
            <Cascader
              disabled={enabled === 'false'}
              options={colorOptions}
              placeholder=""
              getPopupContainer={() => document.getElementById('chart-custom-drawer-form')}
              displayRender={(label, selectedOptions) => selectedOptions[0] ? <div style={{background: selectedOptions[1].value, width: '20px', height: '20px'}}></div> : ''}
            />
          )}
        </Form.Item>
      </Col>)
      fields.push(<Col span={12} key={'axis' + i}>
        <Form.Item label="坐标轴">
          {getFieldDecorator(item.field + '$axis', {
            initialValue: item.axis
          })(
            <Radio.Group disabled={enabled === 'false'} onChange={this.axisChange}>
              <Radio value="left">左侧</Radio>
              <Radio value="right">右侧</Radio>
              <Radio value="unset">不显示</Radio>
            </Radio.Group>
          )}
        </Form.Item>
      </Col>)
      fields.push(<Col span={12} key={'label' + i}>
        <Form.Item label="标注-值">
          {getFieldDecorator(item.field + '$label', {
            initialValue: item.label
          })(
            <Radio.Group disabled={enabled === 'false'}>
              <Radio value="true">显示</Radio>
              <Radio value="false">隐藏</Radio>
            </Radio.Group>
          )}
        </Form.Item>
      </Col>)
    })
    return fields
  }
  axisChange = (e) => {
    const { plot } = this.state
    let val = e.target.value
    let fieldvalue = {}
    plot.customs.forEach(item => {
      if (this.props.form.getFieldValue(item.field + '$axis') === val) {
        fieldvalue[item.field + '$axis'] = 'unset'
      }
    })
    this.props.form.setFieldsValue(fieldvalue)
  }
  enabledChange = (e) => {
    let val = e.target.value
    this.setState({enabled: val})
  }
  onSubmit = () => {
    const { plot, view, datatype } = this.state
    if (view !== 'custom') {
      this.props.form.validateFieldsAndScroll((err, values) => {
        if (!err) {
          let _plot = {...plot, ...values}
          if (datatype === 'query') {
            if (_plot.enabled === 'true') {
              if (_plot.customs.map(_cell => _cell.field).sort().toString() !== _plot.Yaxis.sort().toString()) {
                _plot.customs = null
                _plot.enabled = 'false'
              }
            }
          } else {
            _plot.customs = null
            _plot.enabled = 'false'
          }
          this.setState({
            plot: _plot,
            visible: false
          })
          this.props.plotchange(_plot)
        }
      })
    } else {
      this.props.form.validateFieldsAndScroll((err, values) => {
        if (!err) {
          let _plot = {...plot, enabled: values.enabled}
          if (_plot.enabled === 'true') {
            _plot.customs = _plot.Yaxis.map(field => {
              let _item = {field: field}
              _item.$shape = values[field + '$shape']
              _item.chartType = _item.$shape[0]
              _item.shape = _item.$shape[1]
              _item.$color = values[field + '$color']
              _item.color = _item.$color[1]
              _item.axis = values[field + '$axis']
              _item.label = values[field + '$label']
              return _item
            })
          } else {
            _plot.customs = null
          }
          this.setState({
            plot: _plot,
            visible: false
          })
          this.props.plotchange(_plot)
        }
      })
    }
  }
  changeView = () => {
    const { config } = this.props
    const { plot, view } = this.state
    let _view = view === 'normal' ? 'custom' : 'normal'
    if (_view === 'custom') {
      this.props.form.validateFieldsAndScroll((err, values) => {
        if (!err) {
          let _plot = {...plot, ...values}
          if (_plot.enabled !== 'true' || _plot.customs.map(_cell => _cell.field).sort().toString() !== _plot.Yaxis.sort().toString()) {
            _plot.enabled = 'false'
            _plot.customs = _plot.Yaxis.map((field, i) => {
              let _item = {field: field}
              _item.$shape = [_plot.chartType, _plot.shape]
              _item.$color = []
              _item.axis = i === 0 ? 'left' : 'unset'
              _item.label = _plot.label
              return _item
            })
          }
          this.setState({
            enabled: _plot.enabled || 'false',
            plot: _plot,
            view: _view
          })
        }
      })
    } else {
      this.props.form.validateFieldsAndScroll((err, values) => {
        if (!err) {
          let _values = {enabled: values.enabled}
          if (values.enabled === 'true') {
            let _customs = []
            plot.Yaxis.forEach(field => {
              let _item = {field: field}
              _item.$shape = values[field + '$shape']
              _item.chartType = _item.$shape[0]
              _item.shape = _item.$shape[1]
              _item.$color = values[field + '$color']
              _item.color = _item.$color[1]
              _item.axis = values[field + '$axis']
              _item.label = values[field + '$label']
              _customs.push(_item)
            })
            _values.customs = _customs
          } else {
            _values.customs = null
          }
          let _plot = {...plot, ..._values}
          this.setState({
            plot: _plot,
            view: _view,
            formlist: getBarOrLineChartOptionForm(_plot, config.columns)
          })
        }
      })
    }
  }
  changeTab = () => {
  }
  render() {
    const { dict } = this.props
    const { view, visible, disabled } = this.state
    const formItemLayout = {
      labelCol: {
        xs: { span: 24 },
        sm: { span: 6 }
      },
      wrapperCol: {
        xs: { span: 24 },
        sm: { span: 18 }
      }
    }
    return (
      <div className="line-chart-drawer-form">
        <Icon type="edit" onClick={this.showDrawer} />
        <Modal
          wrapClassName="popview-modal menu-chart-edit-modal"
          title="图表编辑"
          visible={visible}
          width={850}
          maskClosable={false}
          okText={dict['model.submit']}
          cancelText={dict['model.cancel']}
          onOk={this.verifySubmit}
          onCancel={() => { this.setState({ visible: false }) }}
          destroyOnClose
        >
          <Tabs activeKey={view} className="menu-chart-edit-box" onChange={this.changeTab}>
            <TabPane tab="基础设置" key="normal">
              <Form {...formItemLayout}>
                <Row gutter={16}>{this.getFields()}</Row>
              </Form>
            </TabPane>
            <TabPane tab="字段集" disabled={disabled} key="custom">
            </TabPane>
          </Tabs>
          {/* {view !== 'custom' ? <Form {...formItemLayout} className="base-setting">
            <Row gutter={16}>{this.getFields()}</Row>
            {datatype === 'query' ? <Row gutter={16}>
              <Button onClick={this.changeView} style={{border: 0, boxShadow: 'unset',float: 'right', color: '#1890ff', marginRight: 12, cursor: 'pointer'}}>自定义设置<Icon style={{marginLeft: 5}} type="right" /></Button>
            </Row> : null}
          </Form> : null}
          {view === 'custom' ? <Form {...formItemLayout} id="chart-custom-drawer-form" className="mingke-table">
            <Row gutter={16} style={{minHeight: 'calc(100vh - 180px)'}}>{this.getCustomFields()}</Row>
            <Row gutter={16}>
              <Button onClick={this.changeView} style={{border: 0, boxShadow: 'unset', color: '#1890ff', marginRight: 12, cursor: 'pointer'}}><Icon style={{marginRight: 5}} type="left" />基本设置</Button>
            </Row>
          </Form> : null} */}
        </Modal>
      </div>
    );
  }
}
export default Form.create()(LineChartDrawerForm)
src/menu/components/chart/antv-bar/chartcompile/index.scss
New file
@@ -0,0 +1,27 @@
.line-chart-drawer-form {
  position: absolute;
  right: 0px;
  top: 50%;
  > .anticon-edit {
    color: #1890ff;
    font-size: 16px;
    margin-right: 5px;
  }
}
.menu-chart-edit-modal {
  .ant-modal-body {
    padding-top: 10px;
    .menu-chart-edit-box {
      .anticon-question-circle {
        color: #c49f47;
        position: relative;
        left: -3px;
      }
      .ant-input-number {
        width: 100%;
      }
    }
  }
}
src/menu/components/chart/antv-bar/index.jsx
@@ -6,14 +6,14 @@
import asyncComponent from '@/utils/asyncComponent'
import zhCN from '@/locales/zh-CN/mob.js'
import enUS from '@/locales/en-US/mob.js'
// import ChartCompileForm from './chartcompile'
import zhCN from '@/locales/zh-CN/model.js'
import enUS from '@/locales/en-US/model.js'
import './index.scss'
const SettingComponent = asyncComponent(() => import('@/menu/datasourcecomponent'))
const SearchComponent = asyncComponent(() => import('@/menu/searchcomponent'))
const ActionComponent = asyncComponent(() => import('@/menu/actioncomponent'))
const ChartCompileForm = asyncComponent(() => import('./chartcompile'))
class antvBarLineChart extends Component {
  static propTpyes = {
@@ -31,10 +31,23 @@
  }
  UNSAFE_componentWillMount () {
    const { card, config } = this.props
    const { card } = this.props
    console.log(config)
    if (card.isNew) {
      let _plot = {
        chartType: card.type, // 图表类型
        enabled: 'false',     // 是否使用自定义设置
        datatype: 'query',    // 数据类型查询或统计
      }
      if (card.subtype === 'bar') {
        _plot.coordinate = 'angle' // 二维坐标或极坐标
        _plot.transpose = 'false'  // 坐标轴变换
      } else if (card.subtype === 'bar1') {
        _plot.coordinate = 'angle'
        _plot.transpose = 'true'
      }
      let _card = {
        uuid: card.uuid,
        type: card.type,
@@ -44,7 +57,7 @@
        scripts: [],
        search: [],
        action: [],
        plot: {type: card.type, Xaxis: '', Yaxis: null}
        plot: _plot
      }
      this.setState({
        card: _card
@@ -96,9 +109,9 @@
  viewrender = () => {
    const { card } = this.state
    if (card.plot.type === 'line') {
    if (card.plot.chartType === 'line') {
      this.linerender()
    } else if (card.plot.type === 'bar') {
    } else if (card.plot.chartType === 'bar') {
      this.barrender()
    }
  }
@@ -370,8 +383,6 @@
    let Y_axis = plot.Yaxis || ['y']
    let data = this.getdata(X_axis, Y_axis)
    console.log(plot)
    console.log(data)
    
    if (plot.enabled !== 'true') {
      const ds = new DataSet()
@@ -400,7 +411,6 @@
        height: plot.height || 400
      })
  
      console.log(dv.rows)
      chart.data(dv.rows)
  
      chart.scale('value', {
@@ -521,7 +531,7 @@
        <div className="chart-header">
          <span className="chart-title">{card.setting.title || ''}</span>
          <SearchComponent
            menu={{MenuID: config.uuid, MenuName: config.MenuName}}
            menu={config}
            config={card}
            sysRoles={config.sysRoles}
            optionLibs={null}
@@ -529,7 +539,8 @@
          />
        </div>
        <ActionComponent
          menu={{ MenuID: config.uuid, MenuName: config.MenuName, MenuNo: config.MenuNo, fstMenuList: config.fstMenuList }}
          type="chart"
          menu={config}
          config={card}
          tabs={[]}
          usefulFields={config.permFuncField || []}
@@ -537,13 +548,11 @@
          updateaction={this.updateComponent}
        />
        <div className="canvas" id={card.uuid}></div>
        {/* <ChartCompileForm
          plot={plot}
          type={plot.chartType}
          config={this.props.config}
        <ChartCompileForm
          config={card}
          dict={this.state.dict}
          plotchange={this.plotChange}
        /> */}
          plotchange={this.updateComponent}
        />
      </div>
    )
  }
src/menu/components/chart/antv-bar/index.scss
@@ -20,4 +20,19 @@
      margin-left: 10px;
    }
  }
  .model-custom-chart-action-list {
    position: absolute;
    right: 0px;
    z-index: 4;
    padding-top: 10px;
    .ant-row .anticon-plus {
      float: right;
    }
    .page-card {
      float: right;
    }
  }
}
src/menu/menushell/index.scss
@@ -10,13 +10,15 @@
    position: relative;
    .remove-component {
      position: absolute;
      right: 40px;
      top: -13px;
      right: 42px;
      top: -16px;
      color: #ff4d4f;
      border-radius: 2px;
      font-size: 16px;
      padding: 5px;
      cursor: pointer;
      opacity: 0;
      transition: opacity 0.2s;
    }
  }
  .mk-component-card:hover {
@@ -36,7 +38,8 @@
    padding: 5px;
    position: absolute;
    right: 0px;
    top: -19px;
    top: -30px;
    opacity: 0;
    transition: opacity 0.2s;
  }
}
src/menu/searchcomponent/dragsearch/card.jsx
@@ -1,6 +1,6 @@
import React from 'react'
import { useDrag, useDrop } from 'react-dnd'
import { Icon, Select, DatePicker, Input } from 'antd'
import { Icon, Select, DatePicker, Input, Popover } from 'antd'
import moment from 'moment'
import DateGroup from '../dategroup'
@@ -8,7 +8,7 @@
const { MonthPicker, WeekPicker, RangePicker } = DatePicker
const Card = ({ id, card, moveCard, findCard, editCard, delCard }) => {
const Card = ({ id, cardIds, card, moveCard, findCard, copyCard, editCard, delCard }) => {
  const originalIndex = findCard(id).index
  const [{ isDragging }, drag] = useDrag({
    item: { type: 'search', id, originalIndex },
@@ -19,13 +19,10 @@
  const [, drop] = useDrop({
    accept: 'search',
    canDrop: () => true,
    drop: (item) => {
      if (!item.hasOwnProperty('originalIndex')) {
      }
    },
    drop: () => {},
    hover({ id: draggedId }) {
      if (!draggedId) return
      if (!cardIds.includes(draggedId)) return
      if (draggedId !== id) {
        const { index: overIndex } = findCard(id)
        moveCard(draggedId, overIndex)
@@ -60,39 +57,45 @@
  }
  return (
    <div className="page-card" style={{ opacity: opacity}}>
      <div ref={node => drag(drop(node))}>
        <div className="ant-form-item">
          {card.type === 'text' ?
            <Input placeholder={card.label} style={{marginTop: '4px'}} value={card.initval} /> : null
          }
          {(card.type === 'multiselect' || card.type === 'select' || card.type === 'link') ?
            <Select placeholder={card.label} value={_defaultValue}></Select> : null
          }
          {card.type === 'date' ?
            <DatePicker placeholder={card.label} value={card.initval ? moment().subtract(card.initval, 'days') : null} /> : null
          }
          {card.type === 'dateweek' ?
            <WeekPicker placeholder={card.label} value={card.initval ? moment().subtract(card.initval * 7, 'days') : null} /> : null
          }
          {card.type === 'datemonth' ?
            <MonthPicker placeholder={card.label} value={card.initval ? moment().subtract(card.initval, 'month') : null} /> : null
          }
          {card.type === 'daterange' ?
            <RangePicker
              className="data-range"
              placeholder={['BeginTime', 'EndTime']}
              renderExtraFooter={() => 'extra footer'}
              value={_defaultValue}
            /> : null
          }
          {card.type === 'group' ? <DateGroup card={card} /> : null }
          <div className="input-mask"></div>
    <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={
      <div className="mk-popover-control">
        <Icon className="edit" title="edit" type="edit" onClick={() => editCard(id)} />
        <Icon className="copy" title="copy" type="copy" onClick={() => copyCard(id)} />
        <Icon className="close" title="delete" type="close" onClick={() => delCard(id)} />
      </div>
    } trigger="hover">
      <div className="page-card" style={{ opacity: opacity}}>
        <div ref={node => drag(drop(node))}>
          <div className="ant-form-item">
            {card.type === 'text' ?
              <Input placeholder={card.label} value={card.initval} /> : null
            }
            {(card.type === 'multiselect' || card.type === 'select' || card.type === 'link') ?
              <Select placeholder={card.label} value={_defaultValue}></Select> : null
            }
            {card.type === 'date' ?
              <DatePicker placeholder={card.label} value={card.initval ? moment().subtract(card.initval, 'days') : null} /> : null
            }
            {card.type === 'dateweek' ?
              <WeekPicker placeholder={card.label} value={card.initval ? moment().subtract(card.initval * 7, 'days') : null} /> : null
            }
            {card.type === 'datemonth' ?
              <MonthPicker placeholder={card.label} value={card.initval ? moment().subtract(card.initval, 'month') : null} /> : null
            }
            {card.type === 'daterange' ?
              <RangePicker
                className="data-range"
                placeholder={['BeginTime', 'EndTime']}
                renderExtraFooter={() => 'extra footer'}
                value={_defaultValue}
              /> : null
            }
            {card.type === 'group' ? <DateGroup card={card} /> : null }
            <div className="input-mask"></div>
          </div>
        </div>
      </div>
      <Icon className="edit" title="edit" type="edit" onClick={() => editCard(id)} />
      <Icon className="edit close" title="delete" type="close" onClick={() => delCard(id)} />
    </div>
    </Popover>
  )
}
export default Card
src/menu/searchcomponent/dragsearch/index.jsx
@@ -32,18 +32,52 @@
    handleMenu(card)
  }
  const copyCard = id => {
    const { card } = findCard(id)
    let copycard = fromJS(card).toJS()
    copycard.uuid = Utils.getuuid()
    copycard.origin = false
    copycard.copyType = 'search'
    copycard.label = copycard.label + '(copy)'
    copycard.focus = true
    let _val = fromJS(copycard).toJS()
    try {
      _val.uuid = Utils.getuuid()
      _val = window.btoa(window.encodeURIComponent(JSON.stringify(_val)))
    } catch {
      console.warn('Stringify Failure')
      _val = ''
    }
    if (_val) {
      let oInput = document.createElement('input')
      oInput.value = _val
      document.body.appendChild(oInput)
      oInput.select()
      document.execCommand('Copy')
      document.body.removeChild(oInput)
    }
    const { index: overIndex } = findCard(id)
    const _cards = update(cards, { $splice: [[overIndex + 1, 0, copycard]] })
    handleList(_cards, copycard)
  }
  const delCard = id => {
    const { card } = findCard(id)
    deleteMenu(card)
  }
  let cardIds = cards.map(card => card.uuid)
  const [, drop] = useDrop({
    accept: 'search',
    drop(item) {
      if (item.hasOwnProperty('originalIndex')) {
        return
      }
    }
    drop() {}
  })
  const addsearch = (e) => {
@@ -81,9 +115,11 @@
        <Col key={card.uuid} span={card.ratio || 6}>
          <Card
            id={`${card.uuid}`}
            cardIds={cardIds}
            card={card}
            moveCard={moveCard}
            editCard={editCard}
            copyCard={copyCard}
            delCard={delCard}
            findCard={findCard}
          />
src/menu/searchcomponent/index.scss
@@ -1,5 +1,5 @@
.model-custom-search-list {
  padding: 0px;
  padding: 5px 0px 0px;
  .anticon-question-circle {
    color: #c49f47;
@@ -16,7 +16,7 @@
    color: #26C281;
    float: right;
    padding: 5px;
    margin-top: 11px;
    margin-top: 7px;
  }
  .page-card {
    position: relative;
@@ -29,10 +29,6 @@
      .ant-select {
        width: 100%;
        margin-top: 4px;
      }
      .ant-calendar-picker {
        margin-top: 4px;
      }
      .input-mask {
        position: absolute;
@@ -47,28 +43,6 @@
        padding: 4px 20px 4px 5px;
        font-size: 13px;
      }
    }
    .edit {
      position: absolute;
      left: 5px;
      top: 5px;
      color: #1890ff;
      cursor: pointer;
      display: none;
      z-index: 3;
    }
    .edit.copy {
      left: 20px;
      color: #26C281;
    }
    .edit.close {
      left: 30px;
      color: #ff4d4f;
    }
  }
  .page-card:hover {
    .edit {
      display: inline-block;
    }
  }
  .ant-calendar-picker {
src/router/index.js
@@ -2,6 +2,7 @@
import {HashRouter, Switch, Route, Redirect} from 'react-router-dom'
import md5 from 'md5'
import moment from 'moment'
import options from '@/store/options.js'
import asyncComponent from '@/utils/asyncComponent'
import asyncLoadComponent from '@/utils/asyncLoadComponent'
@@ -23,7 +24,7 @@
  {path: '/mobmanage', name: 'mobmanage', component: MobManage, auth: true},
  {path: '/mobdesign/:appId/:appType/:appCode/:appName', name: 'mobdesign', component: MobDesign, auth: true},
  {path: '/menudesign/:MenuId/:ParentId/:MenuName/:MenuNo', name: 'menudesign', component: MenuDesign, auth: true},
  {path: '/main/:param', name: 'pmain', component: Main, auth: true}
  {path: '/paramsmain/:param', name: 'pmain', component: Main, auth: true}
]
export default class RouteConfig extends Component {
@@ -39,9 +40,17 @@
        let _cell = cell.split('=')
        p[_cell[0]] = _cell[1]
      })
      sessionStorage.setItem('UserID', p.ud)
      sessionStorage.setItem('LoginUID', p.ld)
      sessionStorage.setItem('User_Name', p.un)
      !sessionStorage.getItem('UserID') && sessionStorage.setItem('UserID', p.ud)
      !sessionStorage.getItem('LoginUID') && sessionStorage.setItem('LoginUID', p.ld)
      !sessionStorage.getItem('User_Name') && sessionStorage.setItem('User_Name', p.un)
      if (p.mlogo) {
        window.GLOB.mainlogo = p.mlogo
      }
      if (options.styles[p.mstyle]) {
        document.getElementById('root').className = options.styles[p.mstyle]
      }
      sessionStorage.setItem('MainMenu', p.mm)
      sessionStorage.setItem('SubMenu', p.sm)
      sessionStorage.setItem('ThirdMenu', p.tm)
@@ -70,7 +79,8 @@
    if (userId && isauth) {
      return (<item.component {...props}/>)
    } else {
      return (<Redirect to={{ pathname: '/login', state: {from: props.location}}}/>)
      // return (<Redirect to={{ pathname: '/login', state: {from: props.location}}}/>)
      return (<Redirect to={{ pathname: '/login'}}/>)
    }
  }
src/store/options.js
@@ -3,6 +3,9 @@
  sysType: 'bG9j$mkYWw=', // yun ( Y2xv$mkdWQ= ) 、 dandian ( U1$mkNP ) 、 yewu ( bG9j$mkYWw= )
  caId: 'MjAyMDAxMTYxMjMzMzU1MDd$mkGQzkyMzI1Rjk4MDY0QUNGQjQ2Mg==',
  cakey: 'MjAyMDAxMTYxMjQwMDQ2NDM$mk2N0QzODE2MjExNUI0MTc4OTVDMQ==',
  cdomain: 'aHR0cDovL2Nsb3V$mkkLm1rOWguY24=' // window.btoa('') 域名 不带 /
  // cdomain: 'aHR0cDovL2Nsb3VkLnBv$mkc2l0ZWNncm91cC5jb206ODA4MA==' // bao—shi-de
  cdomain: 'aHR0cDovL2Nsb3V$mkkLm1rOWguY24=',                        // window.btoa('') 域名 不带 /
  // cdomain: 'aHR0cDovL2Nsb3VkLnBv$mkc2l0ZWNncm91cC5jb206ODA4MA==', // bao—shi-de
  styles: {
    white: 'mk-white'
  }
}
src/templates/modalconfig/dragelement/card.jsx
@@ -1,8 +1,7 @@
import React from 'react'
import { useDrag, useDrop } from 'react-dnd'
import { Icon, Select, DatePicker, Input, InputNumber, Button } from 'antd'
import { Icon, Select, DatePicker, Input, InputNumber, Button, Popover } from 'antd'
import moment from 'moment'
import ItemTypes from './itemtypes'
import './index.scss'
const { MonthPicker } = DatePicker
@@ -11,13 +10,13 @@
const Card = ({ id, card, cols, moveCard, findCard, editCard, closeCard, copyCard, hasDrop }) => {
  const originalIndex = findCard(id).index
  const [{ isDragging }, drag] = useDrag({
    item: { type: ItemTypes.form, id, originalIndex },
    item: { type: 'form', id, originalIndex },
    collect: monitor => ({
      isDragging: monitor.isDragging(),
    }),
  })
  const [, drop] = useDrop({
    accept: ItemTypes.form,
    accept: 'form',
    canDrop: () => true,
    drop: (item) => {
      if (!item.hasOwnProperty('originalIndex')) {
@@ -98,22 +97,27 @@
  }
  return (
    <div className="page-card" style={{ opacity: opacity}}>
      <div ref={node => drag(drop(node))}>
        {<div className="ant-row ant-form-item">
          <div className={'ant-col ant-form-item-label ant-col-xs-24 ' + labelCol}>
            <label title={card.label}>{card.label}</label>
            <Icon className="edit" type="edit" onClick={edit} />
            <Icon className="edit close" type="close" onClick={close} />
            <Icon className="edit copy" type="copy" onClick={copy} />
          </div>
          <div className={'ant-col ant-form-item-control-wrapper ant-col-xs-24 ' + wrapCol}>
            {formItem}
            <div className="input-mask"></div>
          </div>
        </div>}
    <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={
      <div className="mk-popover-control">
        <Icon className="edit" type="edit" onClick={edit} />
        <Icon className="copy" type="copy" onClick={copy} />
        <Icon className="close" type="close" onClick={close} />
      </div>
    </div>
    } trigger="hover">
      <div className="page-card" style={{ opacity: opacity}}>
        <div ref={node => drag(drop(node))}>
          {<div className="ant-row ant-form-item">
            <div className={'ant-col ant-form-item-label ant-col-xs-24 ' + labelCol}>
              <label title={card.label}>{card.label}</label>
            </div>
            <div className={'ant-col ant-form-item-control-wrapper ant-col-xs-24 ' + wrapCol}>
              {formItem}
              <div className="input-mask"></div>
            </div>
          </div>}
        </div>
      </div>
    </Popover>
  )
}
export default Card
src/templates/modalconfig/dragelement/index.jsx
@@ -5,7 +5,6 @@
import { Col } from 'antd'
import Utils from '@/utils/utils.js'
import Card from './card'
import ItemTypes from './itemtypes'
import './index.scss'
const Container = ({list, group, setting, placeholder, handleList, handleForm, closeForm }) => {
@@ -18,7 +17,7 @@
    if (!card) return
    const _cards = update(cards, { $splice: [[index, 1], [atIndex, 0, card]] })
    setCards(_cards)
    if (!group) {
      handleList(_cards)
    } else {
@@ -58,11 +57,10 @@
  }
  const [, drop] = useDrop({
    accept: ItemTypes.form,
    accept: 'form',
    drop(item) {
      if (item.hasOwnProperty('originalIndex') && group) {
        const { card } = findCard(item.id)
        if (!card) {
          handleList(cards, group, item.id)
        }
src/templates/modalconfig/dragelement/itemtypes.js
File was deleted
src/templates/modalconfig/index.jsx
@@ -5,7 +5,7 @@
import { DndProvider } from 'react-dnd'
import HTML5Backend from 'react-dnd-html5-backend'
import moment from 'moment'
import { Button, Card, Modal, Collapse, notification, Select, List, Icon, Empty } from 'antd'
import { Button, Card, Modal, Collapse, notification, Select, List, Icon, Empty, Popover } from 'antd'
import Api from '@/api'
import Utils from '@/utils/utils.js'
@@ -400,6 +400,8 @@
    if (type === 'copy') {
      card.originUuid = card.uuid
      card.uuid = Utils.getuuid()
      card.label = card.label + '(copy)'
      card.field = card.field + '(copy)'
      card.focus = true
      // 复制到剪切板
@@ -1340,11 +1342,17 @@
                      config.groups.map(group => {
                        return (
                          <div key={group.uuid}>
                            <p className={'group-title' + (group.default ? ' default' : '')}>
                              <span>{group.label}</span>
                              <Icon className="edit" type="edit" onClick={() => {this.handleGroup(group)}} />
                              <Icon className="edit close" type="close" onClick={() => {this.closeGroup(group)}} />
                            </p>
                            <div className="group-title">
                              {!group.default ? <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={
                                <div className="mk-popover-control">
                                  <Icon className="edit" type="edit" onClick={() => {this.handleGroup(group)}} />
                                  <Icon className="edit close" type="close" onClick={() => {this.closeGroup(group)}} />
                                </div>
                              } trigger="hover">
                                <span>{group.label}</span>
                              </Popover> : null}
                              {group.default ? <span style={{color: '#bcbcbc'}}>{group.label}</span> : null}
                            </div>
                            <DragElement
                              group={group}
                              list={group.sublist}
src/templates/modalconfig/index.scss
@@ -160,25 +160,9 @@
          margin-bottom: 10px;
          padding-top: 10px;
          border-bottom: 1px solid #e8e8e8;
          .edit {
            position: absolute;
            left: 0;
            top: 0px;
            color: #1890ff;
            cursor: pointer;
            display: none;
          }
          .edit.close {
            left: 20px;
            color: #ff4d4f;
          }
        }
        .group-title.default {
          color: #bcbcbc;
        }
        .group-title:not(.default):hover {
          .edit {
            display: inline-block;
          span {
            padding: 0 5px 5px;
          }
        }
        > .ant-row {
@@ -197,7 +181,7 @@
          position: relative;
          background: #ffffff;
          border-radius: 2px;
          padding-top: 15px;
          margin-bottom: 15px;
          .ant-form-item {
            cursor: move;
            display: flex;
@@ -213,22 +197,6 @@
                display: inline-block;
                text-overflow: ellipsis;
                white-space: nowrap;
              }
              .edit {
                position: absolute;
                right: 50px;
                top: -5px;
                color: #1890ff;
                cursor: pointer;
                display: none;
              }
              .edit.close {
                right: 10px;
                color: #ff4d4f;
              }
              .edit.copy {
                right: 30px;
                color: #26C281;
              }
            }
            .ant-form-item-control-wrapper {
@@ -258,15 +226,6 @@
            }
            .ant-col-cuswrap {
              width: 89.5%;
            }
          }
        }
        .page-card:hover {
          .ant-form-item {
            .ant-form-item-label {
              .edit {
                display: inline-block;
              }
            }
          }
        }
src/templates/sharecomponent/actioncomponent/dragaction/card.jsx
@@ -1,6 +1,6 @@
import React from 'react'
import { useDrag, useDrop } from 'react-dnd'
import { Icon, Button } from 'antd'
import { Icon, Button, Popover } from 'antd'
import './index.scss'
const Card = ({ id, card, moveCard, findCard, editCard, delCard, copyCard, profileCard, hasDrop, doubleClickCard }) => {
@@ -39,22 +39,27 @@
  }
  return (
    <div className="page-card" style={{ opacity: opacity}}>
      <div ref={node => drag(drop(node))}>
        <Button
          className={'mk-btn mk-' + card.class}
          icon={card.icon}
          key={card.uuid}
          onDoubleClick={() => doubleClickCard(id)}
        >
          {card.label}{card.position === 'grid' && <Icon type="table" />}
        </Button>
    <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={
      <div className="mk-popover-control">
        <Icon className="edit" title="edit" type="edit" onClick={() => editCard(id)} />
        <Icon className="copy" title="copy" type="copy" onClick={() => copyCard(id)} />
        <Icon className="close" title="close" type="close" onClick={() => delCard(id)} />
        {hasProfile ? <Icon className="profile" title="setting" type="profile" onClick={() => profileCard(id)} /> : null}
      </div>
      <Icon className="edit" title="edit" type="edit" onClick={() => editCard(id)} />
      <Icon className="edit copy" title="copy" type="copy" onClick={() => copyCard(id)} />
      <Icon className="edit close" title="close" type="close" onClick={() => delCard(id)} />
      {hasProfile ? <Icon className="edit profile" title="setting" type="profile" onClick={() => profileCard(id)} /> : null}
    </div>
    } trigger="hover">
      <div className="page-card" style={{ opacity: opacity}}>
        <div ref={node => drag(drop(node))}>
          <Button
            className={'mk-btn mk-' + card.class}
            icon={card.icon}
            key={card.uuid}
            onDoubleClick={() => doubleClickCard(id)}
          >
            {card.label}{card.position === 'grid' && <Icon type="table" />}
          </Button>
        </div>
      </div>
    </Popover>
  )
}
export default Card
src/templates/sharecomponent/actioncomponent/dragaction/index.scss
@@ -3,4 +3,4 @@
  line-height: 65px;
  text-align: center;
  color: #bcbcbc;
}
}
src/templates/sharecomponent/actioncomponent/index.jsx
@@ -915,7 +915,7 @@
    }
    return (
      <div className="model-table-action-list" style={config.charts.length > 1 ? {paddingTop: 15} : null}>
      <div className="model-table-action-list" style={config.charts.length > 1 ? {paddingTop: 25} : null}>
        <Tooltip placement="bottomLeft" overlayClassName="middle" title={dict['model.tooltip.action.guide']}>
          <Icon type="question-circle" />
        </Tooltip>
src/templates/sharecomponent/actioncomponent/index.scss
@@ -1,7 +1,7 @@
.model-table-action-list {
  position: relative;
  padding: 0px 25px 15px;
  min-height: 82px;
  padding: 15px 25px 15px;
  min-height: 65px;
  
  .anticon-question-circle {
    color: #c49f47;
@@ -11,35 +11,15 @@
  }
  > .ant-row {
    min-height: 80px;
    min-height: 65px;
  }
  .page-card {
    display: inline-block;
    margin: 0px 0px 0px 0px;
    padding: 15px 10px 0 0;
    padding: 0px 10px 0 0;
    position: relative;
    div {
      cursor: move;
    }
    .edit {
      position: absolute;
      left: 0;
      top: 0px;
      color: #1890ff;
      cursor: pointer;
      display: none;
    }
    .edit.copy {
      left: 20px;
      color: #26C281;
    }
    .edit.close {
      left: 40px;
      color: #ff4d4f;
    }
    .edit.profile {
      left: 60px;
      color: purple;
    }
    button {
      min-width: 65px;
@@ -50,11 +30,6 @@
        right: 1px;
        bottom: 0px;
      }
    }
  }
  .page-card:hover {
    .edit {
      display: inline-block;
    }
  }
}
src/templates/sharecomponent/cardcomponent/index.scss
@@ -15,6 +15,7 @@
      .ant-card-head-title {
        color: rgba(0, 0, 0, 0.85);
        font-weight: 500;
        min-width: 30px;
      }
      .ant-card-extra {
        color: #1890ff;
src/templates/sharecomponent/chartgroupcomponent/dragchartview/card.jsx
@@ -1,6 +1,6 @@
import React from 'react'
import { useDrag, useDrop } from 'react-dnd'
import { Icon } from 'antd'
import { Icon, Popover } from 'antd'
import './index.scss'
const Card = ({ id, card, moveCard, findCard, editCard, delCard }) => {
@@ -36,13 +36,18 @@
  })
  return (
    <div className="chart-tab" style={{ opacity: opacity}}>
      <div ref={node => drag(drop(node))}>
        <Icon type={card.icon} />
    <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={
      <div className="mk-popover-control">
        <Icon className="edit" title="编辑" type="edit" onClick={edit} />
        {card.chartType !== 'table' ? <Icon className="edit close" title="删除" type="close" onClick={del} /> : null}
      </div>
      <Icon className="edit" title="编辑" type="edit" onClick={edit} />
      {card.chartType !== 'table' ? <Icon className="edit close" title="删除" type="close" onClick={del} /> : null}
    </div>
    } trigger="hover">
      <div className="chart-tab" style={{ opacity: opacity}}>
        <div ref={node => drag(drop(node))}>
          <Icon type={card.icon} />
        </div>
      </div>
    </Popover>
  )
}
export default Card
src/templates/sharecomponent/chartgroupcomponent/dragchartview/index.scss
@@ -1,6 +1,7 @@
.chart-edit-tab-box {
  padding-right: 100px;
  display: inline-block;
  padding-top: 15px;
  .ant-tabs-bar {
    border: 0;
@@ -15,21 +16,11 @@
  .chart-tab {
    position: relative;
    width: 40px;
    padding-top: 15px;
    text-align: center;
    display: inline-block;
    
    .edit {
      position: absolute;
      left: 0;
      top: 0px;
      color: #1890ff;
      cursor: pointer;
      display: none;
    }
    .edit.close {
      left: 20px;
      color: #ff4d4f;
    .anticon {
      margin-right: 0;
    }
  }
src/templates/sharecomponent/columncomponent/dragcolumn/card.jsx
@@ -1,6 +1,6 @@
import React from 'react'
import { useDrag, useDrop } from 'react-dnd'
import { Icon } from 'antd'
import { Icon, Popover } from 'antd'
import './index.scss'
const Card = ({ id, card, showfield, moveCard, findCard, editCard, delCard, markCard, hasDrop }) => {
@@ -31,29 +31,34 @@
  const opacity = isDragging ? 0 : 1
  return (
    <div className="page-card" style={{ flex: card.Width, opacity: opacity}}>
      <div ref={node => drag(drop(node))}>
        <span className="ant-table-header-column">
          <div className="ant-table-column-sorters" title={card.label} style={{textAlign: card.Align}}>
            <span className="ant-table-column-title">{card.label}</span>
            {card.IsSort === 'true' ?
              <span className="ant-table-column-sorter">
                <Icon type="caret-up" />
                <Icon type="caret-down" />
              </span> : null
            }
          </div>
          {showfield ?
            <div className="ant-table-column-fields">
              <span className="ant-table-column-title">{card.type === 'colspan' ? card.subfield : card.field}</span>
            </div> : null
          }
        </span>
    <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={
      <div className="mk-popover-control">
        <Icon className="edit" title="edit" type="edit" onClick={() => editCard(id)} />
        <Icon className="close" title="delete" type="close" onClick={() => delCard(id)} />
        {['text', 'number'].includes(card.type) && !card.origin ? <Icon className="profile" title="mark" type="ant-design" onClick={() => markCard(id)} /> : null}
      </div>
      <Icon className="edit" title="edit" type="edit" onClick={() => editCard(id)} />
      <Icon className="edit close" title="delete" type="close" onClick={() => delCard(id)} />
      {['text', 'number'].includes(card.type) && !card.origin ? <Icon className="edit mark" title="mark" type="ant-design" onClick={() => markCard(id)} /> : null}
    </div>
    } trigger="hover">
      <div className="page-card" style={{ flex: card.Width, opacity: opacity}}>
        <div ref={node => drag(drop(node))}>
          <span className="ant-table-header-column">
            <div className="ant-table-column-sorters" title={card.label} style={{textAlign: card.Align}}>
              <span className="ant-table-column-title">{card.label}</span>
              {card.IsSort === 'true' ?
                <span className="ant-table-column-sorter">
                  <Icon type="caret-up" />
                  <Icon type="caret-down" />
                </span> : null
              }
            </div>
            {showfield ?
              <div className="ant-table-column-fields">
                <span className="ant-table-column-title">{card.type === 'colspan' ? card.subfield : card.field}</span>
              </div> : null
            }
          </span>
        </div>
      </div>
    </Popover>
  )
}
export default Card
src/templates/sharecomponent/columncomponent/dragcolumn/index.scss
@@ -3,4 +3,4 @@
  line-height: 65px;
  text-align: center;
  color: #bcbcbc;
}
}
src/templates/sharecomponent/columncomponent/index.scss
@@ -66,30 +66,9 @@
          top: 3px;
        }
      }
      .edit {
        position: absolute;
        left: 0;
        top: 0px;
        color: #1890ff;
        cursor: pointer;
        display: none;
      }
      .edit.close {
        left: 20px;
        color: #ff4d4f;
      }
      .edit.mark {
        left: 40px;
        color: #9254de;
      }
      .ant-checkbox-inner {
        margin-top: 14px;
        margin-left: calc(50% - 8px);
      }
    }
    .page-card:hover {
      .edit {
        display: inline-block;
      }
    }
    .page-card:not(:last-child) {
src/templates/sharecomponent/searchcomponent/dragsearch/card.jsx
@@ -1,6 +1,6 @@
import React from 'react'
import { useDrag, useDrop } from 'react-dnd'
import { Icon, Select, DatePicker, Input } from 'antd'
import { Icon, Select, DatePicker, Input, Popover } from 'antd'
import moment from 'moment'
import DateGroup from '../dategroup'
@@ -60,45 +60,50 @@
  }
  return (
    <div className="page-card" style={{ opacity: opacity}}>
      <div ref={node => drag(drop(node))}>
        <div className="ant-row ant-form-item">
          <div className="ant-col ant-form-item-label ant-col-xs-24 ant-col-sm-8">
            <label className={card.required === 'true' ? 'ant-form-item-required' : ''} title={card.label}>{card.label}</label>
          </div>
          <div className="ant-col ant-form-item-control-wrapper ant-col-xs-24 ant-col-sm-16">
            {card.type === 'text' ?
              <Input style={{marginTop: '4px'}} value={card.initval} /> : null
            }
            {(card.type === 'multiselect' || card.type === 'select' || card.type === 'link') ?
              <Select value={_defaultValue}></Select> : null
            }
            {card.type === 'date' ?
              <DatePicker value={card.initval ? moment().subtract(card.initval, 'days') : null} /> : null
            }
            {card.type === 'dateweek' ?
              <WeekPicker value={card.initval ? moment().subtract(card.initval * 7, 'days') : null} /> : null
            }
            {card.type === 'datemonth' ?
              <MonthPicker value={card.initval ? moment().subtract(card.initval, 'month') : null} /> : null
            }
            {card.type === 'daterange' ?
              <RangePicker
                className="data-range"
                placeholder={['BeginTime', 'EndTime']}
                renderExtraFooter={() => 'extra footer'}
                value={_defaultValue}
              /> : null
            }
            {card.type === 'group' ? <DateGroup card={card} /> : null }
            <div className="input-mask"></div>
    <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={
      <div className="mk-popover-control">
        <Icon className="edit" title="edit" type="edit" onClick={() => editCard(id)} />
        <Icon className="copy" title="copy" type="copy" onClick={() => copyCard(id)} />
        <Icon className="close" title="delete" type="close" onClick={() => delCard(id)} />
      </div>
    } trigger="hover">
      <div className="page-card" style={{ opacity: opacity}}>
        <div ref={node => drag(drop(node))}>
          <div className="ant-row ant-form-item">
            <div className="ant-col ant-form-item-label ant-col-xs-24 ant-col-sm-8">
              <label className={card.required === 'true' ? 'ant-form-item-required' : ''} title={card.label}>{card.label}</label>
            </div>
            <div className="ant-col ant-form-item-control-wrapper ant-col-xs-24 ant-col-sm-16">
              {card.type === 'text' ?
                <Input style={{marginTop: '4px'}} value={card.initval} /> : null
              }
              {(card.type === 'multiselect' || card.type === 'select' || card.type === 'link') ?
                <Select value={_defaultValue}></Select> : null
              }
              {card.type === 'date' ?
                <DatePicker value={card.initval ? moment().subtract(card.initval, 'days') : null} /> : null
              }
              {card.type === 'dateweek' ?
                <WeekPicker value={card.initval ? moment().subtract(card.initval * 7, 'days') : null} /> : null
              }
              {card.type === 'datemonth' ?
                <MonthPicker value={card.initval ? moment().subtract(card.initval, 'month') : null} /> : null
              }
              {card.type === 'daterange' ?
                <RangePicker
                  className="data-range"
                  placeholder={['BeginTime', 'EndTime']}
                  renderExtraFooter={() => 'extra footer'}
                  value={_defaultValue}
                /> : null
              }
              {card.type === 'group' ? <DateGroup card={card} /> : null }
              <div className="input-mask"></div>
            </div>
          </div>
        </div>
      </div>
      <Icon className="edit" title="edit" type="edit" onClick={() => editCard(id)} />
      <Icon className="edit copy" title="copy" type="copy" onClick={() => copyCard(id)} />
      <Icon className="edit close" title="delete" type="close" onClick={() => delCard(id)} />
    </div>
    </Popover>
  )
}
export default Card
src/templates/sharecomponent/searchcomponent/dragsearch/index.scss
@@ -3,4 +3,4 @@
  line-height: 65px;
  text-align: center;
  color: #bcbcbc;
}
}
src/templates/sharecomponent/searchcomponent/index.scss
@@ -22,7 +22,7 @@
    position: relative;
    background: #ffffff;
    border-radius: 2px;
    padding-top: 15px;
    padding-bottom: 15px;
    .ant-form-item {
      cursor: move;
      display: flex;
src/templates/sharecomponent/tabscomponent/index.scss
@@ -14,32 +14,15 @@
        position: relative;
        padding: 0px;
        > div {
          padding: 12px 0px 0px;
          padding: 0px;
          cursor: move;
        }
      }
      .ant-tabs-tab {
        cursor: default;
        .edit {
          position: absolute;
          left: 0;
          top: 0px;
          color: #1890ff;
          cursor: pointer;
          display: none;
        }
        .edit.close {
          left: 20px;
          color: #ff4d4f;
        }
      }
      .ant-tabs-bar {
        min-height: 55px;
      }
      .ant-tabs-tab:hover {
        .edit {
          display: inline-block;
        }
        min-height: 43px;
      }
      .ant-tabs-content {
        .ant-tabs-tabpane img {
src/templates/sharecomponent/tabscomponent/tabdragelement/card.jsx
@@ -1,9 +1,9 @@
import React from 'react'
import { useDrag, useDrop } from 'react-dnd'
import { Icon } from 'antd'
import { Icon, Popover } from 'antd'
import './index.scss'
const Card = ({ id, card, moveCard, findCard, doubleClickCard, hasDrop }) => {
const Card = ({ id, card, moveCard, findCard, doubleClickCard, editCard, delCard, hasDrop }) => {
  const originalIndex = findCard(id).index
  const [{ isDragging }, drag] = useDrag({
    item: { type: 'tabs', id, originalIndex },
@@ -32,15 +32,30 @@
    doubleClickCard(id)
  }
  const edit = () => {
    editCard(id)
  }
  const del = () => {
    delCard(id)
  }
  const opacity = isDragging ? 0 : 1
  return (
    <div className="page-card" style={{ opacity: opacity}}>
      <div ref={node => drag(drop(node))} onDoubleClick={doubleClick}>
        {card.icon ? <Icon type={card.icon} /> : null}
        {card.label}
    <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={
      <div className="mk-popover-control">
        <Icon className="edit" type="edit" onClick={edit} />
        <Icon className="close" type="close" onClick={del} />
      </div>
    </div>
    } trigger="hover">
      <div className="page-card" style={{ opacity: opacity}}>
        <div ref={node => drag(drop(node))} onDoubleClick={doubleClick}>
          {card.icon ? <Icon type={card.icon} /> : null}
          {card.label}
        </div>
      </div>
    </Popover>
  )
}
export default Card
src/templates/sharecomponent/tabscomponent/tabdragelement/index.jsx
@@ -2,7 +2,7 @@
import { useDrop } from 'react-dnd'
import update from 'immutability-helper'
import { is, fromJS } from 'immutable'
import { Tabs, Icon } from 'antd'
import { Tabs } from 'antd'
import Utils from '@/utils/utils.js'
import Card from './card'
import './index.scss'
@@ -75,24 +75,32 @@
    doubleClickCard(card)
  }
  const editCard = id => {
    const { card } = findCard(id)
    handleMenu(card)
  }
  const delCard = id => {
    const { card } = findCard(id)
    deleteMenu(card)
  }
  return (
    <div ref={drop} className="ant-row model-tab-drag-list">
      <Tabs defaultActiveKey="0">
        {cards.map((card, index) => (
          <TabPane tab={
            <div key={card.uuid}>
              <Card
                key={card.uuid}
                id={`${card.uuid}`}
                card={card}
                moveCard={moveCard}
                findCard={findCard}
                hasDrop={hasDrop}
                doubleClickCard={doubleClickBab}
              />
              <Icon className="edit" type="edit" onClick={() => handleMenu(card)} />
              <Icon className="edit close" type="close" onClick={() => deleteMenu(card)} />
            </div>
            <Card
              key={card.uuid}
              id={`${card.uuid}`}
              card={card}
              moveCard={moveCard}
              findCard={findCard}
              editCard={editCard}
              delCard={delCard}
              hasDrop={hasDrop}
              doubleClickCard={doubleClickBab}
            />
          } key={`${index}`}>
            《{card.label}》标签
          </TabPane>
src/templates/sharecomponent/tabscomponent/tabdragelement/index.scss
@@ -5,7 +5,7 @@
  }
  .commontab-drawarea-placeholder {
    position: absolute;
    top: 25px;
    top: 18px;
    left: calc(50% - 50px);
    color: #bcbcbc;
  }
src/views/login/index.jsx
@@ -17,6 +17,12 @@
const LoginCloudForm = asyncLoadComponent(() => import('./logincloudform'))
const iszhCN = localStorage.getItem('lang') !== 'en-US'
const _href = window.location.href.split('#')[0]
if (localStorage.getItem(_href + 'paramsmain')) {
  sessionStorage.setItem('history', localStorage.getItem(_href + 'paramsmain'))
  localStorage.removeItem(_href + 'paramsmain')
}
class Login extends Component {
  state = {
    selectedlang: iszhCN ? 'zh-CN' : 'en-US',
@@ -91,9 +97,16 @@
        localStorage.removeItem(_url)
      }
      if (this.props.location.state && this.props.location.state.from.pathname) {
      // if (this.props.location.state && this.props.location.state.from.pathname) {
      //   // 查看是否为其他页面跳转,路径存在时,跳回原页面
      //   this.props.history.replace(this.props.location.state.from.pathname)
      // }
      let _history = sessionStorage.getItem('history')
      if (_history) {
        sessionStorage.removeItem('history')
        // 查看是否为其他页面跳转,路径存在时,跳回原页面
        this.props.history.replace(this.props.location.state.from.pathname)
        this.props.history.replace(_history)
      } else {
        this.props.history.replace('/main')
      }
@@ -131,9 +144,11 @@
      localStorage.setItem('lang', param.lang || 'zh-CN')
      if (this.props.location.state && this.props.location.state.from.pathname) {
      let _history = sessionStorage.getItem('history')
      if (_history) {
        sessionStorage.removeItem('history')
        // 查看是否为其他页面跳转,路径存在时,跳回原页面
        this.props.history.replace(this.props.location.state.from.pathname)
        this.props.history.replace(_history)
      } else {
        this.props.history.replace('/main')
      }
@@ -296,6 +311,11 @@
            })
            window.GLOB.mainlogo = systemMsg.mainlogo
            window.GLOB.style = systemMsg.style
            if (window.GLOB.style && options.styles[window.GLOB.style]) {
              document.getElementById('root').className = options.styles[window.GLOB.style]
            }
            if (res.titlelogo && window.GLOB.favicon !== res.titlelogo) {
              let link = document.querySelector("link[rel*='icon']") || document.createElement('link')
src/views/menudesign/index.jsx
@@ -81,6 +81,12 @@
  submitConfig = () => {
    const { config, openEdition, parentId } = this.state
    let _config = fromJS(config).toJS()
    delete _config.fstMenuList
    delete _config.permFuncField
    delete _config.sysRoles
    delete _config.tableFields
    let param = {
      func: 'sPC_TrdMenu_AddUpt',
      ParentID: parentId,
@@ -90,7 +96,7 @@
      Template: '',
      MenuName: '',
      PageParam: '',
      LongParam: window.btoa(window.encodeURIComponent(JSON.stringify(config))),
      LongParam: window.btoa(window.encodeURIComponent(JSON.stringify(_config))),
      // LText: _vals.func.map(item => `select '${menu.MenuID}' as MenuID,'${item.func}' as ProcName,'${item.label}' as MenuName`),
      // LTexttb: _tables.map(item => `select '${menu.MenuID}' as MenuID,'${item}' as tbName`),
      TypeCharOne: 'mob'
@@ -147,6 +153,7 @@
          config = {
            version: 1.0,
            uuid: this.props.match.params.MenuId,
            MenuID: this.props.match.params.MenuId,
            Template: 'CustomPage',
            easyCode: '',
            enabled: false,