king
2020-09-24 bcef9a2845e6800704fecb3eb60c204f80854a07
2020-09-24
42个文件已修改
6个文件已添加
3个文件已删除
1256 ■■■■ 已修改文件
src/assets/css/action.scss 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/css/main.scss 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/mobimg/card2.png 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/actioncomponent/actionform/index.jsx 57 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/actioncomponent/dragaction/card.jsx 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/actioncomponent/dragaction/index.jsx 7 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/actioncomponent/formconfig.jsx 38 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/actioncomponent/index.jsx 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/actioncomponent/index.scss 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/card/data-card/index.jsx 42 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/card/data-card/index.scss 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/card/data-card/wrapsetting/index.jsx 80 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/card/data-card/wrapsetting/index.scss 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/card/data-card/wrapsetting/settingform/index.jsx 152 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/card/data-card/wrapsetting/settingform/index.scss 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/chart/antv-bar/chartcompile/formconfig.jsx 36 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/chart/antv-bar/chartcompile/index.scss 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/chart/antv-bar/index.jsx 52 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/chart/antv-bar/index.scss 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/tabs/antv-tabs/index.jsx 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/tabs/antv-tabs/index.scss 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/tabs/tabcomponents/card.jsx 11 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/tabs/tabcomponents/index.jsx 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/tabs/tabcomponents/index.scss 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/tabs/tabsetting/index.jsx 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/tabs/tabsetting/index.scss 91 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/tabs/tabsetting/settingform/index.jsx 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/tabs/tabsetting/settingform/index.scss 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/datasource/index.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/datasource/index.scss 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/datasource/verifycard/settingform/index.jsx 76 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/menushell/card.jsx 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/menushell/index.jsx 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/menushell/index.scss 33 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/modelsource/dragsource/index.jsx 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/modelsource/dragsource/index.scss 19 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/modelsource/option.jsx 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/shellcomponent/card.jsx 56 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/shellcomponent/index.jsx 121 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/shellcomponent/index.scss 49 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/mob/mobshell/card.jsx 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/mob/mobshell/index.scss 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/chart/antv-bar-line/index.jsx 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/chart/antv-bar-line/index.scss 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/share/tabtransfer/index.jsx 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/index.jsx 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/normalTable/index.scss 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/settingcalcomponent/index.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/settingcalcomponent/index.scss 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/asyncIconComponent.jsx 30 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/option.js 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/css/action.scss
@@ -158,4 +158,39 @@
  .mk-icon.mk-orange, .mk-icon.mk-border-orange {
    color: orange;
  }
  // 链接颜色
  .mk-link, .mk-link:hover, .mk-link:active, .mk-link:focus {
    background: transparent;
    .anticon {
      margin-left: 5px;
    }
  }
  .mk-link.mk-gray {
    color: #666;
  }
  .mk-link.mk-primary, .mk-link.mk-border-primary {
    color: #1890ff;
  }
  .mk-link.mk-default, .mk-link.mk-dashed {
    color: rgba(0, 0, 0, 0.65);
  }
  .mk-link.mk-danger, .mk-link.mk-red, .mk-link.mk-border-danger {
    color: #ff4d4f;
  }
  .mk-link.mk-green, .mk-link.mk-border-green {
    color: #26C281;
  }
  .mk-link.mk-dgreen, .mk-link.mk-border-dgreen {
    color: #32c5d2;
  }
  .mk-link.mk-purple, .mk-link.mk-border-purple {
    color: #8E44AD;
  }
  .mk-link.mk-yellow, .mk-link.mk-border-yellow {
    color: #c49f47;
  }
  .mk-link.mk-orange, .mk-link.mk-border-orange {
    color: orange;
  }
}
src/assets/css/main.scss
@@ -255,7 +255,7 @@
.popview-modal {
  .ant-modal-body {
    min-height: 300px;
    max-height: calc(100vh - 160px);
    max-height: calc(100vh - 190px);
    overflow-y: auto;
  }
  .ant-modal-body::-webkit-scrollbar {
@@ -307,7 +307,7 @@
      .profile {
        color: purple;
      }
      .model-menu-tabs-setting {
      .model-datasource {
        display: inline-block;
        position: unset;
      }
@@ -316,8 +316,8 @@
      position: absolute;
      content: ' ';
      width: 100%;
      height: 10px;
      bottom: -10px;
      height: 12px;
      bottom: -12px;
      left: 0px;
    }
    .ant-popover-inner-content {
src/assets/mobimg/card2.png
src/menu/actioncomponent/actionform/index.jsx
@@ -11,15 +11,15 @@
const { TextArea } = Input
const actionTypeOptions = {
  pop: ['label', 'position', 'OpenType', 'intertype', 'Ot', 'icon', 'class', 'execSuccess', 'execError'],
  prompt: ['label', 'position', 'OpenType', 'intertype', 'Ot', 'icon', 'class', 'execSuccess', 'execError'],
  exec: ['label', 'position', 'OpenType', 'intertype', 'Ot', 'icon', 'class', 'execSuccess', 'execError'],
  excelIn: ['label', 'Ot', 'OpenType', 'intertype', 'icon', 'class', 'sheet', 'execSuccess', 'execError'],
  excelOut: ['label', 'OpenType', 'intertype', 'icon', 'class', 'execSuccess', 'execError', 'pagination', 'search'],
  popview: ['label', 'Ot', 'OpenType', 'icon', 'class', 'position', 'tabType', 'linkTab', 'popClose'],
  tab: ['label', 'Ot', 'OpenType', 'icon', 'class', 'position', 'linkmenu'],
  innerpage: ['label', 'Ot', 'OpenType', 'pageTemplate', 'icon', 'class', 'position'],
  funcbutton: ['label', 'OpenType', 'funcType', 'icon', 'class']
  pop: ['label', 'OpenType', 'intertype', 'Ot', 'show', 'icon', 'class', 'execSuccess', 'execError'],
  prompt: ['label', 'OpenType', 'intertype', 'Ot', 'show', 'icon', 'class', 'execSuccess', 'execError'],
  exec: ['label', 'OpenType', 'intertype', 'Ot', 'show', 'icon', 'class', 'execSuccess', 'execError'],
  excelIn: ['label', 'Ot', 'OpenType', 'intertype', 'show', 'icon', 'class', 'sheet', 'execSuccess', 'execError'],
  excelOut: ['label', 'OpenType', 'intertype', 'show', 'icon', 'class', 'execSuccess', 'execError', 'pagination', 'search'],
  popview: ['label', 'Ot', 'OpenType', 'show', 'icon', 'class', 'tabType', 'linkTab', 'popClose'],
  tab: ['label', 'Ot', 'OpenType', 'show', 'icon', 'class', 'linkmenu'],
  innerpage: ['label', 'Ot', 'OpenType', 'pageTemplate', 'show', 'icon', 'class'],
  funcbutton: ['label', 'OpenType', 'funcType', 'show', 'icon', 'class']
}
class MainSearch extends Component {
@@ -37,7 +37,6 @@
    openType: null,  // 打开方式
    interType: null, // 接口类型:内部、外部
    funcType: null,  // 功能类型
    position: null,  // 按钮位置
    requireOptions: [{
      value: 'notRequired',
      text: this.props.dict['header.form.notRequired']
@@ -98,7 +97,6 @@
      openType: _opentype,
      menulist: _menulist.options || [],
      interType: _intertype,
      position: card.position || 'toolbar',
      funcType: _funcType,
      formlist: this.props.formlist.map(item => {
        if (item.key === 'class') {
@@ -106,7 +104,7 @@
        } else if (item.key === 'icon') {
          item.options = btnIcons
        } else if (item.key === 'Ot') {
          if (card.position === 'grid' || card.pageTemplate === 'pay') { // 行级按钮、支付按钮,只能选单行
          if (card.pageTemplate === 'pay') { // 行级按钮、支付按钮,只能选单行
            item.options = this.state.requireOptions.filter(op => ['requiredSgl'].includes(op.value))
          } else if (['innerpage', 'blank', 'tab', 'popview', 'excelIn'].includes(_opentype)) {
            item.options = this.state.requireOptions.filter(op => ['notRequired', 'requiredSgl'].includes(op.value))
@@ -214,10 +212,7 @@
        if (item.key === 'intertype') {
          _fieldval.intertype = this.state.interType
        } else if (item.key === 'Ot') {
          if (this.state.position === 'grid') {
            item.options = this.state.requireOptions.filter(op => ['requiredSgl'].includes(op.value))
            _fieldval.Ot = 'requiredSgl'
          } else if (['innerpage', 'blank', 'tab', 'popview'].includes(value)) {
          if (['innerpage', 'blank', 'tab', 'popview'].includes(value)) {
            item.options = this.state.requireOptions.filter(op => ['notRequired', 'requiredSgl'].includes(op.value))
            _fieldval.Ot = 'requiredSgl'
          } else if (value === 'excelIn') {
@@ -250,28 +245,6 @@
          _fieldval.class = 'dgreen'
        }
        this.props.form.setFieldsValue(_fieldval)
      })
    } else if (key === 'position') {
      let _fieldval = {}
      this.setState({
        position: value,
        formlist: this.state.formlist.map(item => {
          if (item.key === 'Ot') {
            if (value === 'grid') {
              item.options = this.state.requireOptions.filter(op => ['requiredSgl'].includes(op.value))
              _fieldval.Ot = 'requiredSgl'
            } else if (['innerpage', 'blank', 'tab', 'popview'].includes(this.state.openType)) {
              item.options = this.state.requireOptions.filter(op => ['notRequired', 'requiredSgl'].includes(op.value))
              _fieldval.Ot = 'requiredSgl'
            } else {
              item.options = this.state.requireOptions
            }
          }
          return item
        })
      }, () => {
        this.props.form.setFieldsValue(_fieldval)
      })
    } else if (key === 'tabType') {
@@ -355,7 +328,7 @@
        this.props.form.setFieldsValue(_fieldval)
      })
    } else if (key === 'pageTemplate') {
      let _options = ['label', 'Ot', 'OpenType', 'pageTemplate', 'icon', 'class', 'position']
      let _options = ['label', 'Ot', 'OpenType', 'pageTemplate', 'icon', 'class']
      let _fieldval = {}
      if (value === 'custom') {
        _options.push('url', 'joint')
@@ -670,8 +643,8 @@
          values.uuid = this.props.card.uuid
          values.verify = this.props.card.verify || null
          if (values.OpenType === 'excelIn') {
            values.position = 'toolbar'
          if (values.show === 'icon') {
          } else if (values.OpenType === 'excelOut') {
            if (values.intertype === 'system' && setting.interType !== 'system') {
              notification.warning({
@@ -682,13 +655,11 @@
              return
            }
            
            values.position = 'toolbar'
            values.Ot = 'notRequired'
          } else if (values.OpenType === 'popview' && !values.linkTab) { // 没有关联标签(新建时),创建新标签Id
            values.linkTab = Utils.getuuid()
            values.createTab = true // 用于标记按钮复制时,是否复制原有标签
          } else if (values.OpenType === 'funcbutton') { // 转换打印时打开方式
            values.position = 'toolbar'
            if (values.funcType === 'print') {
              values.OpenType = values.execMode
            }
src/menu/actioncomponent/dragaction/card.jsx
@@ -3,7 +3,7 @@
import { Icon, Button, Popover } from 'antd'
import './index.scss'
const Card = ({ id, cardIds, type, card, moveCard, findCard, editCard, delCard, copyCard, profileCard, doubleClickCard }) => {
const Card = ({ id, cardIds, card, moveCard, findCard, editCard, delCard, copyCard, profileCard, doubleClickCard }) => {
  const originalIndex = findCard(id).index
  const [{ isDragging }, drag] = useDrag({
    item: { type: 'action', id, originalIndex },
@@ -37,8 +37,10 @@
  }
  let btnElement = null
  if (type === 'chart') {
    btnElement = (<Icon type={card.icon} className={'mk-icon mk-' + card.class} onClick={() => editCard(id)} />)
  if (card.show === 'icon') {
    btnElement = (<Icon type={card.icon} className={'mk-icon mk-' + card.class}/>)
  } else if (card.show === 'link') {
    btnElement = (<span className={'mk-link mk-' + card.class}>{card.label}{card.icon ? <Icon type={card.icon}/> : null}</span>)
  } else {
    btnElement = (
      <Button
src/menu/actioncomponent/dragaction/index.jsx
@@ -110,12 +110,16 @@
    newcard.class = 'default'
    newcard.intertype = 'system'
    newcard.method = 'POST'
    newcard.position = 'toolbar'
    newcard.execSuccess = 'grid'
    newcard.execError = 'never'
    newcard.popClose = 'never'
    newcard.errorTime = 10
    newcard.verify = null
    newcard.show = 'icon'
    if (type === 'chart') {
      newcard.show = 'icon'
    }
    
    let targetId = cards.length > 0 ? cards[cards.length - 1].uuid : 0
@@ -136,7 +140,6 @@
          id={card.uuid}
          key={card.uuid}
          cardIds={cardIds}
          type={type}
          card={card}
          moveCard={moveCard}
          copyCard={copyCard}
src/menu/actioncomponent/formconfig.jsx
@@ -231,20 +231,6 @@
    },
    {
      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',
@@ -331,10 +317,27 @@
    },
    {
      type: 'select',
      key: 'show',
      label: "显示为",
      initVal: card.show || 'icon',
      required: true,
      options: [{
        value: 'icon',
        text: '图标'
      }, {
        value: 'button',
        text: '按钮'
      }, {
        value: 'link',
        text: '链接'
      }]
    },
    {
      type: 'select',
      key: 'icon',
      label: Formdict['model.icon'],
      initVal: card.icon,
      required: type === 'chart', // 图表必须使用图标
      required: false,
      options: []
    },
    {
@@ -404,7 +407,8 @@
    // }
  ]
  if (type === 'chart') {
  // if (type === 'chart') {
  //   return forms
  // }
    return forms
  }
}
src/menu/actioncomponent/index.jsx
@@ -894,11 +894,10 @@
    const { actionlist, visible, card, dict, copying, profVisible } = this.state
    return (
      <div className="model-custom-chart-action-list">
      <div className="model-menu-action-list">
        <DragElement
          type={type}
          list={actionlist}
          setting={this.props.config.setting}
          handleList={this.handleList}
          handleMenu={this.handleAction}
          deleteMenu={this.deleteElement}
src/menu/actioncomponent/index.scss
@@ -1,4 +1,4 @@
.model-custom-chart-action-list {
.model-menu-action-list {
  .anticon-question-circle {
    color: #c49f47;
    position: absolute;
@@ -13,11 +13,13 @@
  }
  .page-card {
    display: inline-block;
    margin: 0px;
    padding: 0px 5px;
    position: relative;
    div {
      display: inline-block;
      cursor: move;
    }
    button {
src/menu/components/card/data-card/index.jsx
@@ -2,20 +2,24 @@
import PropTypes from 'prop-types'
import {connect} from 'react-redux'
import { is, fromJS } from 'immutable'
import { Icon, Popover } from 'antd'
import asyncComponent from '@/utils/asyncComponent'
import asyncIconComponent from '@/utils/asyncIconComponent'
import Utils from '@/utils/utils.js'
import zhCN from '@/locales/zh-CN/model.js'
import enUS from '@/locales/en-US/model.js'
import './index.scss'
const SettingComponent = asyncComponent(() => import('@/menu/datasource'))
const SettingComponent = asyncIconComponent(() => import('@/menu/datasource'))
const WrapComponent = asyncIconComponent(() => import('./wrapsetting'))
const ActionComponent = asyncComponent(() => import('@/menu/actioncomponent'))
class antvBarLineChart extends Component {
  static propTpyes = {
    card: PropTypes.object,
    deletecomponent: PropTypes.func,
    updateConfig: PropTypes.func,
  }
@@ -46,15 +50,18 @@
        tabId: card.tabId || '',
        parentId: card.parentId || '',
        format: 'array',   // 组件属性 - 数据格式
        pageable: false,   // 组件属性 - 是否可分页
        switchable: false, // 组件属性 - 数据是否可切换
        pageable: true,    // 组件属性 - 是否可分页
        switchable: true,  // 组件属性 - 数据是否可切换
        dataName: dataName,
        width: 24,
        name: card.name,
        subtype: card.subtype,
        setting: {span: 24, height: 200, interType: 'system', name: card.name},
        setting: { interType: 'system' },
        wrap: { name: card.name, width: 24, height: 200, cardWidth: 6, addable: 'false', switch: 'false' },
        columns: [],
        scripts: [],
        search: [],
        action: [],
        elements: []
      }
      this.setState({
        card: _card
@@ -88,6 +95,10 @@
    this.setState({
      card: component
    })
    component.width = component.wrap.width
    component.name = component.wrap.name
    this.props.updateConfig(component)
  }
@@ -95,22 +106,25 @@
    const { card } = this.state
    return (
      <div className="menu-data-card-edit-box" style={{height: card.setting.height || 400}}>
        <SettingComponent
          config={card}
          updateConfig={this.updateComponent}
        />
        <div className="chart-header">
          <span className="chart-title">{card.setting.title || ''}</span>
      <div className="menu-data-card-edit-box">
        <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={
          <div className="mk-popover-control">
            <WrapComponent config={card} updateConfig={this.updateComponent} />
            <Icon className="close" title="delete" type="delete" onClick={() => this.props.deletecomponent(card.uuid)} />
            <SettingComponent config={card} updateConfig={this.updateComponent} />
        </div>
        } trigger="hover">
          <Icon type="tool" />
        </Popover>
        <div className={'ant-col card-item ant-col-' + (card.wrap.cardWidth || 6)} style={{height: card.wrap.height ? card.wrap.height + 'px' : 'auto'}}>
        <ActionComponent
          type="chart"
          config={card}
          tabs={[]}
          // setSubConfig={(_btn) => this.setSubConfig(_btn, 'button')}
          updateaction={this.updateComponent}
        />
        <div className="canvas" id={card.uuid}></div>
        </div>
      </div>
    )
  }
src/menu/components/card/data-card/index.scss
@@ -3,6 +3,30 @@
  box-sizing: border-box;
  background: #ffffff;
  
  .anticon-tool {
    position: absolute;
    z-index: 1;
    font-size: 16px;
    right: 0;
    top: 0;
    cursor: pointer;
    padding: 10px;
  }
  .card-item {
    position: relative;
    min-height: 50px;
    border: 1px solid #e8e8e8;
  }
  .card-item:hover {
    box-shadow: 0px 0px 2px #e8e8e8;
  }
}
.menu-data-card-edit-box::after {
  display: block;
  content: ' ';
  clear: both;
}
.menu-data-card-edit-box:hover {
  box-shadow: 0px 0px 2px #e8e8e8;
src/menu/components/card/data-card/wrapsetting/index.jsx
New file
@@ -0,0 +1,80 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import { is, fromJS } from 'immutable'
import { Icon, Modal } from 'antd'
import zhCN from '@/locales/zh-CN/model.js'
import enUS from '@/locales/en-US/model.js'
import SettingForm from './settingform'
import './index.scss'
class DataSource extends Component {
  static propTpyes = {
    config: PropTypes.any,
    updateConfig: PropTypes.func
  }
  state = {
    dict: localStorage.getItem('lang') !== 'en-US' ? zhCN : enUS,
    visible: false,
    wrap: null
  }
  UNSAFE_componentWillMount () {
    const { config } = this.props
    this.setState({wrap: fromJS(config.wrap).toJS()})
  }
  shouldComponentUpdate (nextProps, nextState) {
    return !is(fromJS(this.props), fromJS(nextProps)) || !is(fromJS(this.state), fromJS(nextState))
  }
  editDataSource = () => {
    this.setState({
      visible: true
    })
  }
  verifySubmit = () => {
    const { config } = this.props
    this.verifyRef.handleConfirm().then(res => {
      this.setState({
        wrap: res,
        visible: false
      })
      this.props.updateConfig({...config, wrap: res})
    })
  }
  render () {
    const { visible, dict, wrap } = this.state
    return (
      <div className="model-menu-setting-wrap">
        <Icon type="edit" onClick={() => this.editDataSource()} />
        <Modal
          wrapClassName="popview-modal"
          title={'卡片设置'}
          visible={visible}
          width={700}
          maskClosable={false}
          okText={dict['model.submit']}
          onOk={this.verifySubmit}
          onCancel={() => { this.setState({ visible: false }) }}
          destroyOnClose
        >
          <SettingForm
            dict={dict}
            wrap={wrap}
            wrappedComponentRef={(inst) => this.verifyRef = inst}
          />
        </Modal>
      </div>
    )
  }
}
export default DataSource
src/menu/components/card/data-card/wrapsetting/index.scss
New file
@@ -0,0 +1,7 @@
.model-menu-setting-wrap {
  display: inline-block;
  >.anticon-edit {
    color: #1890ff;
  }
}
src/menu/components/card/data-card/wrapsetting/settingform/index.jsx
New file
@@ -0,0 +1,152 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import { Form, Row, Col, Input, Radio, Tooltip, Icon, InputNumber } from 'antd'
import './index.scss'
class SettingForm extends Component {
  static propTpyes = {
    dict: PropTypes.object,    // 字典项
    wrap: PropTypes.object,    // 数据源配置
  }
  handleConfirm = () => {
    // 表单提交时检查输入值是否正确
    return new Promise((resolve, reject) => {
      this.props.form.validateFieldsAndScroll((err, values) => {
        if (!err) {
          resolve(values)
        } else {
          reject(err)
        }
      })
    })
  }
  render() {
    const { wrap } = this.props
    const { getFieldDecorator } = this.props.form
    const formItemLayout = {
      labelCol: {
        xs: { span: 24 },
        sm: { span: 8 }
      },
      wrapperCol: {
        xs: { span: 24 },
        sm: { span: 16 }
      }
    }
    return (
      <div className="model-menu-setting-form">
        <Form {...formItemLayout}>
          <Row gutter={24}>
            <Col span={12}>
              <Form.Item label={
                <Tooltip placement="topLeft" title="用于组件间的区分。">
                  <Icon type="question-circle" />
                  组件名称
                </Tooltip>
              }>
                {getFieldDecorator('name', {
                  initialValue: wrap.name,
                  rules: [
                    {
                      required: true,
                      message: this.props.dict['form.required.input'] + '组件名称!'
                    }
                  ]
                })(<Input placeholder={''} autoComplete="off" />)}
              </Form.Item>
            </Col>
            <Col span={12}>
              <Form.Item label={
                <Tooltip placement="topLeft" title="栅格布局,每行等分24份。">
                  <Icon type="question-circle" />
                  宽度
                </Tooltip>
              }>
                {getFieldDecorator('width', {
                  initialValue: wrap.width || 24,
                  rules: [
                    {
                      required: true,
                      message: this.props.dict['form.required.input'] + '宽度!'
                    }
                  ]
                })(<InputNumber min={1} max={24} precision={0} />)}
              </Form.Item>
            </Col>
            <Col span={12}>
              <Form.Item label={
                <Tooltip placement="topLeft" title="高度为空时,使用自适应高度。">
                  <Icon type="question-circle" />
                  高度
                </Tooltip>
              }>
                {getFieldDecorator('height', {
                  initialValue: wrap.height
                })(<InputNumber min={50} max={1000} precision={0} />)}
              </Form.Item>
            </Col>
            <Col span={12}>
              <Form.Item label={
                <Tooltip placement="topLeft" title="单个卡片所占的宽度,栅格布局,每行等分24份。">
                  <Icon type="question-circle" />
                  卡片宽度
                </Tooltip>
              }>
                {getFieldDecorator('cardWidth', {
                  initialValue: wrap.cardWidth || 6,
                  rules: [
                    {
                      required: true,
                      message: this.props.dict['form.required.input'] + '卡片宽度!'
                    }
                  ]
                })(<InputNumber min={1} max={24} precision={0} />)}
              </Form.Item>
            </Col>
            <Col span={12}>
              <Form.Item label={
                <Tooltip placement="topLeft" title="选择含有添加按钮时,请完善按钮配置信息。">
                  <Icon type="question-circle" />
                  添加按钮
                </Tooltip>
              }>
                {getFieldDecorator('addable', {
                  initialValue: wrap.addable || 'false'
                })(
                  <Radio.Group>
                    <Radio value="true">有</Radio>
                    <Radio value="false">无</Radio>
                  </Radio.Group>
                )}
              </Form.Item>
            </Col>
            <Col span={12}>
              <Form.Item label={
                <Tooltip placement="topLeft" title="选择卡片切换时,可向其他组件传递主键值。">
                  <Icon type="question-circle" />
                  是否切换
                </Tooltip>
              }>
                {getFieldDecorator('switch', {
                  initialValue: wrap.switch || 'false'
                })(
                  <Radio.Group>
                    <Radio value="true">是</Radio>
                    <Radio value="false">否</Radio>
                  </Radio.Group>
                )}
              </Form.Item>
            </Col>
          </Row>
        </Form>
      </div>
    )
  }
}
export default Form.create()(SettingForm)
src/menu/components/card/data-card/wrapsetting/settingform/index.scss
New file
@@ -0,0 +1,11 @@
.model-menu-setting-form {
  position: relative;
  .anticon-question-circle {
    color: #c49f47;
    margin-right: 3px;
  }
  .ant-input-number {
    width: 100%;
  }
}
src/menu/components/chart/antv-bar/chartcompile/formconfig.jsx
@@ -38,6 +38,42 @@
  return [
    {
      type: 'text',
      key: 'title',
      label: '标题',
      initVal: card.title,
      required: false
    },
    {
      type: 'text',
      key: 'name',
      label: '组件名称',
      initVal: card.name,
      tooltip: '用于组件间的区分。',
      required: true
    },
    {
      type: 'number',
      key: 'width',
      label: '宽度',
      initVal: card.width,
      tooltip: '栅格布局,每行等分24份。',
      min: 1,
      max: 24,
      decimal: 0,
      required: true
    },
    {
      type: 'number',
      key: 'height',
      label: '高度',
      initVal: card.height,
      min: 100,
      max: 1000,
      decimal: 0,
      required: true
    },
    {
      type: 'radio',
      key: 'datatype',
      label: '数据类型',
src/menu/components/chart/antv-bar/chartcompile/index.scss
@@ -1,13 +1,7 @@
.line-chart-drawer-form {
  position: absolute;
  right: 0px;
  top: 50%;
  display: inline-block;
  > .anticon-edit {
    color: #1890ff;
    font-size: 16px;
    margin-right: 5px;
    cursor: pointer;
  }
}
.menu-chart-edit-modal {
src/menu/components/chart/antv-bar/index.jsx
@@ -2,26 +2,29 @@
import PropTypes from 'prop-types'
import {connect} from 'react-redux'
import { is, fromJS } from 'immutable'
import { Icon, Popover } from 'antd'
import { Chart } from '@antv/g2'
import DataSet from '@antv/data-set'
import MKEmitter from '@/utils/events.js'
import asyncComponent from '@/utils/asyncComponent'
import asyncIconComponent from '@/utils/asyncIconComponent'
import Utils from '@/utils/utils.js'
import zhCN from '@/locales/zh-CN/model.js'
import enUS from '@/locales/en-US/model.js'
import './index.scss'
const SettingComponent = asyncComponent(() => import('@/menu/datasource'))
const SettingComponent = asyncIconComponent(() => import('@/menu/datasource'))
const SearchComponent = asyncComponent(() => import('@/menu/searchcomponent'))
const ActionComponent = asyncComponent(() => import('@/menu/actioncomponent'))
const ChartCompileForm = asyncComponent(() => import('./chartcompile'))
const ChartCompileForm = asyncIconComponent(() => import('./chartcompile'))
class antvBarLineChart extends Component {
  static propTpyes = {
    card: PropTypes.object,
    updateConfig: PropTypes.func,
    deletecomponent: PropTypes.func,
  }
  state = {
@@ -38,7 +41,10 @@
        chartType: card.type, // 图表类型
        enabled: 'false',     // 是否使用自定义设置
        datatype: 'query',    // 数据类型查询或统计
        customs: []
        customs: [],
        width: 24,
        height: 400,
        name: card.name
      }
      if (card.subtype === 'bar') {
@@ -74,8 +80,10 @@
        pageable: false,   // 组件属性 - 是否可分页
        switchable: false, // 组件属性 - 数据是否可切换
        dataName: dataName,
        width: _plot.width,
        name: _plot.name,
        subtype: card.subtype,
        setting: {span: 24, height: 400, interType: 'system', name: card.name},
        setting: { interType: 'system' },
        columns: [],
        scripts: [],
        search: [],
@@ -161,7 +169,7 @@
  linerender = () => {
    const { card } = this.state
    let plot = {...card.plot, height: card.setting.height - 70}
    let plot = {...card.plot, height: card.plot.height - 70} // 去除title所占空间
    let transfield = {}
    card.columns.forEach(col => {
@@ -265,7 +273,8 @@
  }
  customrender = (data, transfield) => {
    const { plot } = this.props
    const { card } = this.state
    let plot = {...card.plot, height: card.plot.height - 70} // 去除title所占空间
    let barfields = []
    let fields = []
@@ -414,8 +423,7 @@
  barrender = () => {
    const { card } = this.state
    let plot = {...card.plot, height: card.setting.height - 70}
    let plot = {...card.plot, height: card.plot.height - 70}
    let transfield = {}
    card.columns.forEach(col => {
@@ -556,13 +564,16 @@
  updateComponent = (component) => {
    const card = fromJS(this.state.card).toJS()
    let refresh = false
    if (card.setting.span !== component.setting.span || card.setting.height !== component.setting.height || !is(fromJS(component.plot), fromJS(card.plot))) {
    if (!is(fromJS(component.plot), fromJS(card.plot))) {
      let _element = document.getElementById(card.uuid)
      if (_element) {
        _element.innerHTML = ''
      }
      refresh = true
    }
    component.width = component.plot.width
    component.name = component.plot.name
    
    this.setState({
      card: component
@@ -580,17 +591,22 @@
    const { card } = this.state
    return (
      <div className="menu-line-chart-edit-box" style={{height: card.setting.height || 400}}>
        <SettingComponent
          config={card}
          updateConfig={this.updateComponent}
        />
      <div className="menu-line-chart-edit-box" style={{height: card.plot.height || 400}}>
        <div className="chart-header">
          <span className="chart-title">{card.setting.title || ''}</span>
          <span className="chart-title">{card.plot.title || ''}</span>
          <SearchComponent
            config={card}
            updatesearch={this.updateComponent}
          />
          <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={
            <div className="mk-popover-control">
              <ChartCompileForm config={card} dict={this.state.dict} plotchange={this.updateComponent}/>
              <Icon className="close" title="delete" type="delete" onClick={() => this.props.deletecomponent(card.uuid)} />
              <SettingComponent config={card} updateConfig={this.updateComponent}/>
            </div>
          } trigger="hover">
            <Icon type="tool" />
          </Popover>
        </div>
        <ActionComponent
          type="chart"
@@ -600,11 +616,7 @@
          updateaction={this.updateComponent}
        />
        <div className="canvas" id={card.uuid}></div>
        <ChartCompileForm
          config={card}
          dict={this.state.dict}
          plotchange={this.updateComponent}
        />
      </div>
    )
  }
src/menu/components/chart/antv-bar/index.scss
@@ -9,9 +9,20 @@
  }
  .chart-header {
    position: relative;
    height: 45px;
    border-bottom: 1px solid #e8e8e8;
    overflow: hidden;
    padding-right: 40px;
    >.anticon-tool {
      position: absolute;
      right: 0px;
      top: 0px;
      font-size: 16px;
      padding: 10px;
      cursor: pointer;
    }
    .chart-title {
      font-size: 16px;
@@ -21,7 +32,7 @@
    }
  }
  .model-custom-chart-action-list {
  .model-menu-action-list {
    position: absolute;
    right: 0px;
    z-index: 4;
src/menu/components/tabs/antv-tabs/index.jsx
@@ -5,13 +5,14 @@
import MKEmitter from '@/utils/events.js'
import asyncComponent from '@/utils/asyncComponent'
import asyncIconComponent from '@/utils/asyncIconComponent'
import Utils from '@/utils/utils.js'
import zhCN from '@/locales/zh-CN/model.js'
import enUS from '@/locales/en-US/model.js'
import './index.scss'
const SettingComponent = asyncComponent(() => import('../tabsetting'))
const SettingComponent = asyncIconComponent(() => import('../tabsetting'))
const TabLabelComponent = asyncComponent(() => import('../tablabelform'))
const TabComponents = asyncComponent(() => import('../tabcomponents'))
@@ -21,7 +22,7 @@
class antvBarLineChart extends Component {
  static propTpyes = {
    tabs: PropTypes.object,
    deleteTabs: PropTypes.func,
    deletecomponent: PropTypes.func,
    updateConfig: PropTypes.func,
  }
@@ -43,7 +44,9 @@
        tabId: tabs.tabId || '',
        parentId: tabs.parentId || '',
        subtype: tabs.subtype,
        setting: {span: 24, position: 'top', tabStyle: 'line', name: tabs.name},
        width: 24,
        name: tabs.name,
        setting: {width: 24, position: 'top', tabStyle: 'line', name: tabs.name},
        subtabs: [
          { uuid: Utils.getuuid(), parentId: tabs.uuid, floor: tabs.floor, label: 'Tab 1', icon: '', components: [] },
          { uuid: Utils.getuuid(), parentId: tabs.uuid, floor: tabs.floor, label: 'Tab 2', icon: '', components: [] },
@@ -94,6 +97,9 @@
      // 注册事件-标签变化,通知标签内元素
      MKEmitter.emit('tabsChange', tabs.uuid)
    }
    component.width = component.setting.width
    component.name = component.setting.name
    this.setState({
      tabs: component
@@ -201,7 +207,6 @@
    return (
      <div className="menu-tabs-edit-box">
        {/* <SettingComponent config={tabs} updateConfig={this.updateComponent} /> */}
        <Tabs defaultActiveKey="1" tabPosition={tabs.setting.position} type={tabs.setting.tabStyle}>
          {tabs.subtabs.map((tab, index) => (
            <TabPane tab={
@@ -223,15 +228,14 @@
            <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={
              <div className="mk-popover-control">
                <Icon className="plus" title="add" type="plus" onClick={this.tabAdd} />
                <Icon className="close" title="delete" type="delete" onClick={() => this.props.deleteTabs(tabs.uuid)} />
                <SettingComponent config={tabs} updateConfig={this.updateComponent} />
                <Icon className="close" title="delete" type="delete" onClick={() => this.props.deletecomponent(tabs.uuid)} />
              </div>
            } trigger="hover">
              <Icon type="tool" />
            </Popover>
          } key="tool">
          </TabPane>
          {/* <TabPane className="tab-add" disabled tab={<Icon onClick={this.tabAdd} type="plus" />} key="add"></TabPane> */}
        </Tabs>
        <Modal
          wrapClassName="popview-modal"
src/menu/components/tabs/antv-tabs/index.scss
@@ -9,9 +9,7 @@
  .ant-tabs-bar {
    margin-bottom: 0px;
  }
  .ant-tabs-content {
    padding-top: 20px;
  }
  .ant-tabs .ant-tabs-left-bar .ant-tabs-tab {
    padding: 0px;
    text-align: right;
src/menu/components/tabs/tabcomponents/card.jsx
@@ -1,12 +1,12 @@
import React from 'react'
import { useDrag, useDrop } from 'react-dnd'
import { Icon } from 'antd'
import asyncComponent from '@/utils/asyncComponent'
import './index.scss'
const AntvBar = asyncComponent(() => import('@/menu/components/chart/antv-bar'))
const AntvTabs = asyncComponent(() => import('@/menu/components/tabs/antv-tabs'))
const DataCard = asyncComponent(() => import('@/menu/components/card/data-card'))
const Card = ({ id, card, moveCard, findCard, delCard, hasDrop, updateConfig }) => {
  const originalIndex = findCard(id).index
@@ -38,16 +38,17 @@
  const getCardComponent = () => {
    if (card.type === 'bar' || card.type === 'line') {
      return (<AntvBar card={card} updateConfig={updateConfig} />)
      return (<AntvBar card={card} updateConfig={updateConfig} deletecomponent={delCard} />)
    } else if (card.type === 'tabs') {
      return (<AntvTabs tabs={card} updateConfig={updateConfig} deleteTabs={delCard} />)
      return (<AntvTabs tabs={card} updateConfig={updateConfig} deletecomponent={delCard} />)
    } else if (card.type === 'card' && card.subtype === 'datacard') {
      return (<DataCard card={card} updateConfig={updateConfig} deletecomponent={delCard} />)
    }
  }
  return (
    <div className={'ant-col mk-component-card ant-col-' + (card.setting ? card.setting.span : 24)} ref={node => drag(drop(node))} style={style}>
    <div className={'ant-col mk-component-card ant-col-' + (card.width || 24)} ref={node => drag(drop(node))} style={style}>
      {getCardComponent()}
      {card.type !== 'tabs' ? <Icon className="remove-component" title="delete" type="delete" onClick={() => delCard(id)} /> : null}
    </div>
  )
}
src/menu/components/tabs/tabcomponents/index.jsx
@@ -53,7 +53,7 @@
    }
    confirm({
      title: `确定删除《${card.setting.name}》吗?`,
      title: `确定删除《${card.name}》吗?`,
      content: hasComponent ? '当前组件中含有子组件!' : '',
      onOk() {
        handleList({...config, components: cards.filter(item => item.uuid !== card.uuid)})
@@ -99,7 +99,7 @@
      
      while (!name && names[item.component]) {
        let _name = names[item.component] + i
        if (config.components.filter(com => com.setting && com.setting.name === _name).length === 0) {
        if (config.components.filter(com => com.name === _name).length === 0) {
          name = _name
        }
        i++
src/menu/components/tabs/tabcomponents/index.scss
@@ -10,39 +10,8 @@
  .mk-component-card {
    position: relative;
    .remove-component {
      position: absolute;
      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 {
    >.remove-component {
      opacity: 1;
    }
    > div >.model-datasource .anticon-setting, >.menu-tabs-edit-box > .model-menu-tabs-setting  .anticon-setting {
      opacity: 1;
    }
  }
  >.ant-empty {
    padding: 60px 0px 70px;
  }
  .model-datasource > .anticon-setting, .model-menu-tabs-setting > .anticon-setting {
    font-size: 16px;
    padding: 5px;
    position: absolute;
    right: 0px;
    top: -30px;
    opacity: 0;
    cursor: pointer;
    transition: opacity 0.2s;
  }
}
src/menu/components/tabs/tabsetting/index.jsx
@@ -53,10 +53,10 @@
    const { visible, dict, setting } = this.state
    return (
      <div className="model-menu-tabs-setting">
        <Icon type="setting" onClick={() => this.editDataSource()} />
      <div className="model-menu-setting-wrap">
        <Icon type="edit" onClick={() => this.editDataSource()} />
        <Modal
          wrapClassName="model-datasource-verify-modal popview-modal"
          wrapClassName="popview-modal"
          title={'标签页配置'}
          visible={visible}
          width={700}
src/menu/components/tabs/tabsetting/index.scss
@@ -1,94 +1,7 @@
.model-menu-tabs-setting {
  position: absolute;
  right: 7px;
  top: 5px;
  z-index: 1;
  >.anticon-setting {
    font-size: 18px;
    padding: 10px;
  }
  .model-input-group-wrapper {
    padding: 0 20px;
.model-menu-setting-wrap {
    display: inline-block;
    width: 100%;
    text-align: start;
    vertical-align: top;
    margin-bottom: 15px;
    .model-input-wrapper {
      position: relative;
      display: table;
      width: 100%;
      border-collapse: separate;
      border-spacing: 0;
      .model-input-value {
        display: table-cell;
        width: 100%;
        border: 1px solid #d9d9d9;
        border-radius: 4px 0px 0px 4px;
        overflow: hidden;
        text-overflow:ellipsis;
        white-space: nowrap;
        padding: 2px 10px;
        color: #ffffff;
      }
      .model-input-group-addon {
        display: table-cell;
        width: 1px;
        position: relative;
        padding: 0 11px;
        color: rgba(0, 0, 0, 0.65);
        font-weight: normal;
        font-size: 14px;
        line-height: 1;
        text-align: center;
        background-color: #fafafa;
        border: 1px solid #d9d9d9;
        border-radius: 0px 4px 4px 0px;
        white-space: nowrap;
      }
      .model-input-insert {
        display: table-cell;
        width: 100%;
        border: 1px dotted #d9d9d9;
        border-radius: 4px;
        text-align: center;
        cursor: pointer;
        .anticon-plus {
          padding: 6px;
          font-size: 16px;
          color: rgb(38, 194, 129);
        }
      }
    }
    .anticon-setting {
      margin-right: 5px;
      padding: 6px;
      cursor: pointer;
    }
    .anticon-setting:hover {
  >.anticon-edit {
      color: #1890ff;
    }
    .anticon-close {
      padding: 6px;
      cursor: pointer;
    }
    .anticon-close:hover {
      color: #ff4d4f;
    }
  }
}
.model-datasource-verify-modal {
  .ant-modal {
    top: 50px;
    .ant-modal-body {
      max-height: calc(100vh - 190px);
    }
  }
}
src/menu/components/tabs/tabsetting/settingform/index.jsx
@@ -2,7 +2,6 @@
import PropTypes from 'prop-types'
import { Form, Row, Col, Input, Radio, Tooltip, Icon, InputNumber, Select } from 'antd'
// import { formRule } from '@/utils/option.js'
import './index.scss'
class SettingForm extends Component {
@@ -47,8 +46,8 @@
    }
    return (
      <div className="model-datasource-setting-form-box">
        <Form {...formItemLayout} className="model-setting-form">
      <div className="model-menu-setting-form">
        <Form {...formItemLayout}>
          <Row gutter={24}>
            <Col span={12}>
              <Form.Item label={
@@ -75,8 +74,8 @@
                  宽度
                </Tooltip>
              }>
                {getFieldDecorator('span', {
                  initialValue: setting.span || 12,
                {getFieldDecorator('width', {
                  initialValue: setting.width || 24,
                  rules: [
                    {
                      required: true,
src/menu/components/tabs/tabsetting/settingform/index.scss
@@ -1,22 +1,9 @@
.model-datasource-setting-form-box {
.model-menu-setting-form {
  position: relative;
  .model-setting-form {
    .data-source {
      .ant-form-item-label {
        width: 11%;
      }
      .ant-form-item-control-wrapper {
        width: 89%;
      }
      .CodeMirror {
        height: 150px;
      }
    }
    .anticon-question-circle {
      color: #c49f47;
      margin-right: 3px;
    }
  }
  .ant-input-number {
    width: 100%;
src/menu/datasource/index.jsx
@@ -60,7 +60,7 @@
      <div className="model-datasource">
        <Icon type="setting" onClick={() => this.editDataSource()} />
        <Modal
          wrapClassName="model-datasource-verify-modal popview-modal"
          wrapClassName="popview-modal"
          title={'数据源配置'}
          visible={visible}
          width={'75vw'}
src/menu/datasource/index.scss
@@ -84,11 +84,3 @@
    }
  }
}
.model-datasource-verify-modal {
  .ant-modal {
    top: 50px;
    .ant-modal-body {
      max-height: calc(100vh - 190px);
    }
  }
}
src/menu/datasource/verifycard/settingform/index.jsx
@@ -1,6 +1,6 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import { Form, Row, Col, Input, Radio, Tooltip, Icon, notification, InputNumber, Select } from 'antd'
import { Form, Row, Col, Input, Radio, Tooltip, Icon, notification, Select, InputNumber } from 'antd'
import { formRule } from '@/utils/option.js'
import Utils from '@/utils/utils.js'
@@ -160,49 +160,7 @@
      <div className="model-datasource-setting-form-box">
        <Form {...formItemLayout} className="model-setting-form">
          <Row gutter={24}>
            <Col span={8}>
              <Form.Item label="标题">
                {getFieldDecorator('title', {
                  initialValue: setting.title
                })(<Input placeholder={''} autoComplete="off" />)}
              </Form.Item>
            </Col>
            <Col span={8}>
              <Form.Item label={
                <Tooltip placement="topLeft" title="用于组件间的区分。">
                  <Icon type="question-circle" />
                  组件名称
                </Tooltip>
              }>
                {getFieldDecorator('name', {
                  initialValue: setting.name,
                  rules: [
                    {
                      required: true,
                      message: this.props.dict['form.required.input'] + '组件名称!'
                    }
                  ]
                })(<Input placeholder={''} autoComplete="off" />)}
              </Form.Item>
            </Col>
            <Col span={8}>
              <Form.Item label={
                <Tooltip placement="topLeft" title="栅格布局,每行等分24份。">
                  <Icon type="question-circle" />
                  宽度
                </Tooltip>
              }>
                {getFieldDecorator('span', {
                  initialValue: setting.span || 12,
                  rules: [
                    {
                      required: true,
                      message: this.props.dict['form.required.input'] + '宽度!'
                    }
                  ]
                })(<InputNumber min={1} max={24} precision={0} />)}
              </Form.Item>
            </Col>
            <Col span={8}>
              <Form.Item label="表名">
                {getFieldDecorator('tableName', {
@@ -288,18 +246,6 @@
                })(<CodeMirror />)}
              </Form.Item>
            </Col> : null}
            <Col span={8}>
              <Form.Item label={
                <Tooltip placement="topLeft" title="高度为空时,使用系统自适应设置。">
                  <Icon type="question-circle" />
                  高度
                </Tooltip>
              }>
                {getFieldDecorator('height', {
                  initialValue: setting.height || 400
                })(<InputNumber min={150} max={1500} precision={0} />)}
              </Form.Item>
            </Col>
            {interType === 'system' ? <Col span={8}>
              <Form.Item label={
                <Tooltip placement="topLeft" title={'查询时,搜索条件以where条件拼接进入sql,统计时,将数据源中以“@+搜索字段+@”的内容,以搜索条件中的值进行替换后,提交查询,注:查询类型仅在使用系统函数时有效。'}>
@@ -412,6 +358,24 @@
                )}
              </Form.Item>
            </Col> : null}
            {config.pageable ? <Col span={8}>
              <Form.Item label={
                <Tooltip placement="topLeft" title="选择分页时有效。">
                  <Icon type="question-circle" />
                  每页数量
                </Tooltip>
              }>
                {getFieldDecorator('pageSize', {
                  initialValue: setting.pageSize || 10,
                  rules: [
                    {
                      required: true,
                      message: this.props.dict['form.required.input'] + '每页数量!'
                    }
                  ]
                })(<InputNumber min={1} max={500} precision={0} />)}
              </Form.Item>
            </Col> : null}
            <Col span={8}>
              <Form.Item label={
                <Tooltip placement="topLeft" title={'使用主搜索条件(存在时),主搜索条件与组件的搜索条件会一同用作数据过滤(组件的搜索条件优先)。'}>
src/menu/menushell/card.jsx
@@ -1,6 +1,5 @@
import React from 'react'
import { useDrag, useDrop } from 'react-dnd'
import { Icon } from 'antd'
import asyncComponent from '@/utils/asyncComponent'
import './index.scss'
@@ -39,18 +38,17 @@
  const getCardComponent = () => {
    if (card.type === 'bar' || card.type === 'line') {
      return (<AntvBar card={card} updateConfig={updateConfig} />)
      return (<AntvBar card={card} updateConfig={updateConfig} deletecomponent={delCard}/>)
    } else if (card.type === 'tabs') {
      return (<AntvTabs tabs={card} updateConfig={updateConfig} deleteTabs={delCard} />)
    } else if (card.type === 'card') {
      return (<DataCard card={card} updateConfig={updateConfig} />)
      return (<AntvTabs tabs={card} updateConfig={updateConfig} deletecomponent={delCard}/>)
    } else if (card.type === 'card' && card.subtype === 'datacard') {
      return (<DataCard card={card} updateConfig={updateConfig} deletecomponent={delCard}/>)
    }
  }
  return (
    <div className={'ant-col mk-component-card ant-col-' + (card.setting ? card.setting.span : 12)} ref={node => drag(drop(node))} style={style}>
    <div className={'ant-col mk-component-card ant-col-' + (card.width || 24)} ref={node => drag(drop(node))} style={style}>
      {getCardComponent()}
      {card.type !== 'tabs' ? <Icon className="remove-component" title="delete" type="delete" onClick={() => delCard(id)} /> : null}
    </div>
  )
}
src/menu/menushell/index.jsx
@@ -53,7 +53,7 @@
    }
    confirm({
      title: `确定删除《${card.setting.name}》吗?`,
      title: `确定删除《${card.name}》吗?`,
      content: hasComponent ? '当前组件中含有子组件!' : '',
      onOk() {
        handleList({...menu, components: cards.filter(item => item.uuid !== card.uuid)})
@@ -91,7 +91,7 @@
      
      while (!name && names[item.component]) {
        let _name = names[item.component] + i
        if (menu.components.filter(com => com.setting && com.setting.name === _name).length === 0) {
        if (menu.components.filter(com => com.name === _name).length === 0) {
          name = _name
        }
        i++
src/menu/menushell/index.scss
@@ -11,16 +11,6 @@
    >.ant-col {
      padding: 8px;
    }
    > .mk-component-card:hover {
      > .remove-component {
        opacity: 1;
      }
      > div {
        > .model-datasource > .anticon-setting, > .model-menu-tabs-setting > .anticon-setting {
          opacity: 1;
        }
      }
    }
  }
  .anticon {
    cursor: unset;
@@ -28,32 +18,9 @@
  .mk-component-card {
    position: relative;
    .remove-component {
      position: absolute;
      right: 42px;
      top: -16px;
      color: #ff4d4f;
      border-radius: 2px;
      font-size: 16px;
      padding: 5px;
      cursor: pointer;
      opacity: 0;
      transition: opacity 0.2s;
    }
  }
  
  >.ant-empty {
    padding-top: 150px;
  }
  .model-datasource > .anticon-setting, .model-menu-tabs-setting > .anticon-setting {
    font-size: 16px;
    padding: 5px;
    position: absolute;
    right: 0px;
    top: -30px;
    opacity: 0;
    cursor: pointer;
    transition: opacity 0.2s;
  }
}
src/menu/modelsource/dragsource/index.jsx
@@ -5,8 +5,9 @@
const MobSourceElement = ({content}) => {
  const [, drag] = useDrag({ item: content })
  return (
    <div ref={drag} className="menu-source-item">
      <img style={{width: '100%'}} src={content.url} alt=""/>
    <div className="menu-source-item">
      <div className="property"><span>{content.title}</span></div>
      <img ref={drag} src={content.url} alt=""/>
    </div>
  )
}
src/menu/modelsource/dragsource/index.scss
@@ -2,13 +2,22 @@
  display: inline-block;
  width: 100%;
  margin-bottom: 15px;
  cursor: move;
  height: auto;
  box-shadow: 0px 0px 1px #1890ff;
  background-size: cover;
  background-position: top center;
  background-repeat: no-repeat;
  // background-size: cover;
  // background-position: top center;
  // background-repeat: no-repeat;
  .property {
    font-size: 14px;
    color: rgba(0, 0, 0, 0.65);
  }
  img {
    width: 100%;
    cursor: move;
    box-shadow: 0px 0px 1px #1890ff;
  }
  .tooltip-block {
    width: 100%;
src/menu/modelsource/option.jsx
@@ -6,15 +6,17 @@
import line1 from '@/assets/mobimg/line1.png'
import tabs from '@/assets/mobimg/tabs.png'
import card1 from '@/assets/mobimg/card1.png'
import card2 from '@/assets/mobimg/card2.png'
// const _dict =  sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS
// 组件配置信息
export const menuOptions = [
  { type: 'menu', url: tabs, component: 'tabs', subtype: 'tabs' },
  { type: 'menu', url: card1, component: 'card', subtype: 'card1' },
  { type: 'menu', url: line, component: 'line', subtype: 'line' },
  { type: 'menu', url: line1, component: 'line', subtype: 'line1' },
  { type: 'menu', url: bar, component: 'bar', subtype: 'bar' },
  { type: 'menu', url: bar1, component: 'bar', subtype: 'bar1' },
  { type: 'menu', url: tabs, component: 'tabs', subtype: 'tabs', title: '标签页' },
  { type: 'menu', url: card1, component: 'card', subtype: 'datacard', title: '数据卡' },
  { type: 'menu', url: card2, component: 'card', subtype: 'propcard', title: '属性卡' },
  { type: 'menu', url: line, component: 'line', subtype: 'line', title: '折线图' },
  { type: 'menu', url: line1, component: 'line', subtype: 'line1', title: '阶梯折线图' },
  { type: 'menu', url: bar, component: 'bar', subtype: 'bar', title: '柱状图' },
  { type: 'menu', url: bar1, component: 'bar', subtype: 'bar1', title: '条形图' },
]
src/menu/shellcomponent/card.jsx
File was deleted
src/menu/shellcomponent/index.jsx
File was deleted
src/menu/shellcomponent/index.scss
File was deleted
src/mob/mobshell/card.jsx
@@ -1,6 +1,5 @@
import React from 'react'
import { useDrag, useDrop } from 'react-dnd'
import { Icon } from 'antd'
import asyncComponent from '@/utils/asyncComponent'
@@ -56,7 +55,6 @@
  return (
    <div className="mk-component-card" ref={node => drag(drop(node))} style={style}>
      {getCardComponent()}
      <Icon className="remove-component" title="delete" type="delete" onClick={() => delCard(id)} />
    </div>
  )
}
src/mob/mobshell/index.scss
@@ -1,22 +1,6 @@
.mob-shell-inner {
  .mk-component-card {
    position: relative;
    .remove-component {
      position: absolute;
      right: 2px;
      top: 50%;
      background: #ff4d4f;
      border-radius: 2px;
      padding: 4px;
      color: #ffffff;
      cursor: pointer;
      display: none;
    }
  }
  .mk-component-card:hover {
    .remove-component {
      display: inline-block;
    }
  }
  >.ant-empty {
    padding-top: 150px;
src/tabviews/custom/components/chart/antv-bar-line/index.jsx
@@ -102,7 +102,7 @@
    }
    let showHeader = false
    if (config.setting.title || _config.plot.datatype === 'statistics') {
    if (config.plot.title || _config.plot.datatype === 'statistics') {
      showHeader = true
    }
@@ -115,7 +115,7 @@
      arr_field: _config.columns.map(col => col.field).join(','),
      plot: _config.plot,
      sync: _sync,
      title: config.setting.title,
      title: config.plot.title,
      search: Utils.initMainSearch(config.search),
      showHeader
    }, () => {
src/tabviews/custom/components/chart/antv-bar-line/index.scss
@@ -1,5 +1,4 @@
.custom-line-chart-plot-box {
  // margin-bottom: 30px;
  background: #ffffff;
  > .chart-header {
src/tabviews/custom/components/share/tabtransfer/index.jsx
@@ -33,13 +33,13 @@
    return config.components.map(item => {
      if (item.type === 'bar' || item.type === 'line') {
        return (
          <Col span={item.setting.span} key={item.uuid}>
          <Col span={item.width} key={item.uuid}>
            <AntvBarAndLine config={item} BID={BID} mainSearch={mainSearch} menuType={menuType} dataManager={dataManager} />
          </Col>
        )
      } else if (item.type === 'tabs') {
        return (
          <Col span={item.setting.span} key={item.uuid}>
          <Col span={item.width} key={item.uuid}>
            <AntvTabs config={item} BID={BID} mainSearch={mainSearch} menuType={menuType} dataManager={dataManager} />
          </Col>
        )
src/tabviews/custom/index.jsx
@@ -440,13 +440,13 @@
    return config.components.map(item => {
      if (item.type === 'bar' || item.type === 'line') {
        return (
          <Col span={item.setting.span} key={item.uuid}>
          <Col span={item.width} key={item.uuid}>
            <AntvBarAndLine config={item} data={data} BID={BID} mainSearch={mainSearch} menuType={menuType} dataManager={dataManager} />
          </Col>
        )
      } else if (item.type === 'tabs') {
        return (
          <Col span={item.setting.span} key={item.uuid}>
          <Col span={item.width} key={item.uuid}>
            <AntvTabs config={item} BID={BID} mainSearch={mainSearch} menuType={menuType} dataManager={dataManager} />
          </Col>
        )
src/tabviews/zshare/normalTable/index.scss
@@ -54,7 +54,7 @@
  }
  .ant-table-body {
    overflow-x: auto!important;
    min-height: 90px;
    // min-height: 90px;
    table {
      .ant-table-tbody > tr > td {
        vertical-align: top;
src/templates/sharecomponent/settingcalcomponent/index.jsx
@@ -62,7 +62,7 @@
      <div className="model-datasource">
        <Icon type="setting" onClick={() => this.editDataSource()} />
        <Modal
          wrapClassName="model-datasource-verify-modal popview-modal"
          wrapClassName="popview-modal"
          title={'数据源配置'}
          visible={visible}
          width={'75vw'}
src/templates/sharecomponent/settingcalcomponent/index.scss
@@ -84,11 +84,3 @@
    }
  }
}
.model-datasource-verify-modal {
  .ant-modal {
    top: 50px;
    .ant-modal-body {
      max-height: calc(100vh - 190px);
    }
  }
}
src/utils/asyncIconComponent.jsx
New file
@@ -0,0 +1,30 @@
import React, {Component} from 'react'
import { Icon } from 'antd'
/**
 * @description 异步加载模块
 * @param {*} importComponent
 */
export default function asyncComponent(importComponent) {
  return class extends Component {
    constructor(props) {
      super(props)
      this.state = {
        component: null
      }
    }
    async componentDidMount() {
      const {default: component} = await importComponent()
      this.setState({component})
    }
    render() {
      const C = this.state.component
      return C ? <C {...this.props} /> : <Icon type="loading" />
    }
  }
}
src/utils/option.js
@@ -261,6 +261,18 @@
}, {
  value: 'unlock',
  text: 'unlock'
}, {
  value: 'right',
  text: 'right'
}, {
  value: 'left',
  text: 'left'
}, {
  value: 'double-right',
  text: 'double-right'
}, {
  value: 'double-left',
  text: 'double-left'
}]
// 按钮颜色集