king
2020-10-15 7449eee8fa9f8a251e9c4e9162030f1e004bae0f
2020-10-15
39个文件已修改
2个文件已添加
2712 ■■■■ 已修改文件
src/components/tabview/index.jsx 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/locales/en-US/model.js 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/locales/zh-CN/model.js 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/card/cardcellcomponent/dragaction/action.jsx 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/card/cardcellcomponent/dragaction/card.jsx 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/card/cardcellcomponent/dragaction/index.jsx 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/card/cardcellcomponent/index.jsx 32 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/card/cardcellcomponent/index.scss 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/chart/antv-bar/chartcompile/formconfig.jsx 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/chart/antv-bar/chartcompile/index.jsx 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/chart/antv-bar/chartcompile/index.scss 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/chart/antv-bar/index.jsx 157 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/chart/antv-bar/index.scss 23 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/tabs/antv-tabs/index.jsx 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/tabs/antv-tabs/index.scss 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/modalconfig/index.jsx 1401 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/modalconfig/index.scss 295 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/searchcomponent/index.jsx 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/commontable/index.jsx 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/card/data-card/index.scss 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/chart/antv-bar-line/index.jsx 7 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/chart/antv-bar-line/index.scss 13 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/tabs/antv-tabs/index.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/tabs/antv-tabs/index.scss 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/normalTable/index.jsx 11 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/calendarconfig/index.jsx 31 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/comtableconfig/index.jsx 30 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/formtabconfig/index.jsx 44 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/menuconfig/editthdmenu/index.jsx 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/modalconfig/dragelement/card.jsx 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/modalconfig/index.jsx 62 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/modalconfig/index.scss 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/modalconfig/source.jsx 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/searchcomponent/index.jsx 18 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/searchcomponent/searchform/index.jsx 28 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/settingcomponent/settingform/datasource/index.jsx 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/subtableconfig/index.jsx 30 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/treepageconfig/index.jsx 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/zshare/formconfig.jsx 71 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/zshare/modalform/index.jsx 163 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/zshare/modalform/modaleditable/index.jsx 117 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/tabview/index.jsx
@@ -206,6 +206,7 @@
  }
  render () {
    const { menuType } = this.props
    const { tabviews } = this.state
    let view = tabviews.filter(tab => tab.selected)[0]
    this.resetWindow(view)
@@ -235,7 +236,7 @@
                    key={view.MenuID}
                  >
                    {this.selectcomponent(view)}
                    {options.sysType !== 'cloud' && !['CommonTable', 'TreePage', 'ManageTable', 'CalendarPage'].includes(view.type) ?
                    {options.sysType !== 'cloud' && menuType !== 'HS' && !['CommonTable', 'TreePage', 'ManageTable', 'CalendarPage'].includes(view.type) ?
                      <Button
                        icon="copy"
                        shape="circle"
@@ -264,6 +265,7 @@
const mapStateToProps = (state) => {
  return {
    menuType: state.editLevel,
    tabviews: state.tabviews,
    collapse: state.collapse,
    isiframe: state.isiframe
src/locales/en-US/model.js
@@ -201,7 +201,7 @@
  'header.form.leftPicRightText': '左图右文',
  'model.form.selectItem.error': '下拉选项设置错误!',
  'header.form.request.method': '请求方式',
  'header.form.readonly': '是否只读',
  'header.form.readonly': '只读',
  'header.form.queryType': '查询类型',
  'header.form.query': '查询',
  'header.form.statistics': '统计',
src/locales/zh-CN/model.js
@@ -201,7 +201,7 @@
  'header.form.leftPicRightText': '左图右文',
  'model.form.selectItem.error': '下拉选项设置错误!',
  'header.form.request.method': '请求方式',
  'header.form.readonly': '是否只读',
  'header.form.readonly': '只读',
  'header.form.queryType': '查询类型',
  'header.form.query': '查询',
  'header.form.statistics': '统计',
src/menu/components/card/cardcellcomponent/dragaction/action.jsx
@@ -3,7 +3,7 @@
import { Icon, Popover, Button } from 'antd'
import './index.scss'
const Card = ({ id, cardIds, card, moveCard, findCard, editCard, delCard, profileCard, changeStyle }) => {
const Card = ({ id, cardIds, card, moveCard, findCard, editCard, delCard, profileCard, changeStyle, doubleClickCard }) => {
  const originalIndex = findCard(id).index
  const [{ isDragging }, drag] = useDrag({
    item: { type: 'action', id, originalIndex },
@@ -53,7 +53,6 @@
        className={'mk-btn mk-' + card.class}
        icon={card.icon}
        style={card.btnstyle}
        // onDoubleClick={() => doubleClickCard(id)}
      >
        {card.label}
      </Button>
@@ -69,9 +68,11 @@
        {hasProfile ? <Icon className="profile" title="setting" type="profile" onClick={() => profileCard(id)} /> : null}
      </div>
    } trigger="hover">
      <div ref={node => drag(drop(node))} className={'ant-col card-button-cell ant-col-' + card.width} style={_style}>
      <div ref={node => drag(drop(node))} className={'ant-col card-button-cell ant-col-' + card.width} onDoubleClick={() => doubleClickCard(id)}>
        <div style={_style}>
        {btnElement}
      </div>
      </div>
    </Popover>
  )
}
src/menu/components/card/cardcellcomponent/dragaction/card.jsx
@@ -96,9 +96,11 @@
        <Icon className="style" title="调整样式" onClick={() => changeStyle(id)} type="font-colors" />
      </div>
    } trigger="hover">
      <div ref={node => drag(drop(node))} className={'ant-col card-cell ant-col-' + card.width} style={_style}>
      <div ref={node => drag(drop(node))} className={'ant-col card-cell ant-col-' + card.width}>
        <div style={_style}>
        {getContent()}
      </div>
      </div>
    </Popover>
  )
}
src/menu/components/card/cardcellcomponent/dragaction/index.jsx
@@ -7,7 +7,7 @@
import Action from './action'
import './index.scss'
const Container = ({list, handleList, handleMenu, deleteMenu, profileAction, handleStyle }) => {
const Container = ({list, handleList, handleMenu, deleteMenu, profileAction, handleStyle, handleSubConfig }) => {
  const [cards, setCards] = useState(list)
  const moveCard = (id, atIndex) => {
    const { card, index } = findCard(id)
@@ -42,6 +42,14 @@
    profileAction(card)
  }
  const doubleClickCard = id => {
    const { card } = findCard(id)
    console.log(card)
    if (card.OpenType === 'pop') {
      handleSubConfig(card)
    }
  }
  const delCard = id => {
    const { card } = findCard(id)
    deleteMenu(card)
@@ -68,6 +76,7 @@
              editCard={editCard}
              changeStyle={changeStyle}
              profileCard={profileCard}
              doubleClickCard={doubleClickCard}
              delCard={delCard}
              findCard={findCard}
            />
src/menu/components/card/cardcellcomponent/index.jsx
@@ -8,21 +8,24 @@
import options from '@/store/options.js'
import zhCN from '@/locales/zh-CN/model.js'
import enUS from '@/locales/en-US/model.js'
import asyncComponent from '@/utils/asyncComponent'
import { getCardCellForm } from './formconfig'
import { getActionForm } from '@/menu/actioncomponent/formconfig'
import MKEmitter from '@/utils/events.js'
import ElementForm from './elementform'
import DragElement from './dragaction'
import ActionForm from '@/menu/actioncomponent/actionform'
import CreateFunc from '@/templates/zshare/createfunc'
import VerifyCard from '@/templates/zshare/verifycard'
import VerifyPrint from '@/menu/actioncomponent/verifyprint'
import VerifyExcelIn from '@/menu/actioncomponent/verifyexcelin'
import VerifyExcelOut from '@/menu/actioncomponent/verifyexcelout'
import './index.scss'
const { confirm } = Modal
const ActionForm = asyncComponent(() => import('@/menu/actioncomponent/actionform'))
const CreateFunc = asyncComponent(() => import('@/templates/zshare/createfunc'))
const VerifyCard = asyncComponent(() => import('@/templates/zshare/verifycard'))
const VerifyPrint = asyncComponent(() => import('@/menu/actioncomponent/verifyprint'))
const VerifyExcelIn = asyncComponent(() => import('@/menu/actioncomponent/verifyexcelin'))
const VerifyExcelOut = asyncComponent(() => import('@/menu/actioncomponent/verifyexcelout'))
// const ModalConfig = asyncComponent(() => import('@/menu/modalconfig'))
class CardCellComponent extends Component {
  static propTpyes = {
@@ -480,6 +483,10 @@
    })
  }
  handleSubConfig = (item) => {
    console.log(item)
  }
  render() {
    const { cards } = this.props
    const { elements, visible, actvisible, profVisible, card, dict } = this.state
@@ -492,8 +499,21 @@
          handleMenu={this.handleElement}
          handleStyle={this.handleStyle}
          profileAction={this.profileAction}
          handleSubConfig={this.handleSubConfig}
          deleteMenu={this.deleteElement}
        />
          {/* <ModalConfig
            menu={this.state.editMenu}
            editTab={this.state.editTab}
            tabConfig={this.state.tabConfig}
            editSubTab={this.state.editSubTab}
            subTabConfig={this.state.subTabConfig}
            btnTab={this.state.btnTab}
            btnTabConfig={this.state.btnTabConfig}
            editAction={this.state.editAction}
            subConfig={this.state.subConfig}
            handleView={this.handleView}
          /> */}
        {/* 编辑按钮:复制、编辑 */}
        <Modal
          title={'编辑元素'}
src/menu/components/card/cardcellcomponent/index.scss
@@ -31,8 +31,8 @@
      }
    }
  }
  .card-cell:hover {
    box-shadow: 0px 0px 1px #d8d8d8;
  .card-cell:hover, .card-button-cell:hover {
    box-shadow: 0px 0px 1px #1890ff;
  }
  .ant-slider {
    margin: 0px;
src/menu/components/chart/antv-bar/chartcompile/formconfig.jsx
@@ -287,6 +287,20 @@
      initVal: card.correction,
      forbid: !['bar'].includes(card.chartType),
      required: false
    }, {
      type: 'color',
      key: 'color',
      label: '色系',
      initVal: card.color || 'rgba(0, 0, 0, 0.85)',
      tooltip: '坐标轴及示例等提示文字使用的颜色。',
      required: false,
      options: [{
        value: 'black',
        text: '黑色'
      }, {
        value: 'white',
        text: '白色'
      }]
    }
  ]
}
src/menu/components/chart/antv-bar/chartcompile/index.jsx
@@ -5,6 +5,7 @@
import { getBarOrLineChartOptionForm } from './formconfig'
import { minkeColorSystem, colorTransform } from '@/utils/option.js'
import ColorSketch from '@/mob/colorsketch'
import './index.scss'
const { TabPane } = Tabs
@@ -215,6 +216,23 @@
            </Form.Item>
          </Col>
        )
      } else if (item.type === 'color') {
        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
              })(
                <ColorSketch />
              )}
            </Form.Item>
          </Col>
        )
      }
    })
    return fields
src/menu/components/chart/antv-bar/chartcompile/index.scss
@@ -22,6 +22,10 @@
        .ant-tabs-nav-wrap {
          text-align: center;
        }
        .color-sketch-block {
          position: relative;
          top: 5px;
        }
      }
    }
  }
src/menu/components/chart/antv-bar/index.jsx
@@ -84,7 +84,7 @@
        name: _plot.name,
        subtype: card.subtype,
        setting: { interType: 'system' },
        style: { marginLeft: '8px', marginRight: '8px', marginTop: '8px', marginBottom: '8px' },
        style: { marginLeft: '8px', marginRight: '8px', marginTop: '8px', marginBottom: '8px', fontSize: '16px' },
        columns: [],
        scripts: [],
        search: [],
@@ -105,6 +105,7 @@
  componentDidMount () {
    this.viewrender()
    MKEmitter.addListener('tabsChange', this.handleTabsChange)
    MKEmitter.addListener('submitStyle', this.getStyle)
  }
  shouldComponentUpdate (nextProps, nextState) {
@@ -119,6 +120,7 @@
      return
    }
    MKEmitter.removeListener('tabsChange', this.handleTabsChange)
    MKEmitter.removeListener('submitStyle', this.getStyle)
  }
  handleTabsChange = (parentId) => {
@@ -170,7 +172,8 @@
  linerender = () => {
    const { card } = this.state
    let plot = {...card.plot, height: card.plot.height - 70} // 去除title所占空间
    let plot = {...card.plot, height: card.plot.height - 80} // 去除title所占空间
    let color = plot.color || 'rgba(0, 0, 0, 0.85)'
    let transfield = {}
    card.columns.forEach(col => {
@@ -213,6 +216,31 @@
  
      chart.data(dv.rows)
  
      chart.axis(X_axis, {
        label: {
          style: {
            fill: color,
          }
        },
        line: {
          style: {
            fill: color,
          }
        }
      })
      chart.axis('value', {
        grid: {
          style: {
            fill: color,
          }
        },
        label: {
          style: {
            fill: color,
          }
        }
      })
      if (plot.coordinate !== 'polar') {
        chart.scale(X_axis, {
          range: [0, 1]
@@ -226,7 +254,12 @@
        chart.legend(false)
      } else {
        chart.legend({
          position: plot.legend
          position: plot.legend,
          itemName: {
            style: {
              fill: color,
            }
          }
        })
      }
  
@@ -275,7 +308,8 @@
  customrender = (data, transfield) => {
    const { card } = this.state
    let plot = {...card.plot, height: card.plot.height - 70} // 去除title所占空间
    let plot = {...card.plot, height: card.plot.height - 80} // 去除title所占空间
    let color = plot.color || 'rgba(0, 0, 0, 0.85)'
    let barfields = []
    let fields = []
@@ -327,6 +361,31 @@
    chart.data(dv.rows)
    chart.axis(plot.Xaxis, {
      label: {
        style: {
          fill: color,
        }
      },
      line: {
        style: {
          fill: color,
        }
      }
    })
    chart.axis('value', {
      grid: {
        style: {
          fill: color,
        }
      },
      label: {
        style: {
          fill: color,
        }
      }
    })
    if (plot.coordinate !== 'polar' && barfields.length === 0) {
      chart.scale(plot.Xaxis, {
        range: [0, 1]
@@ -340,6 +399,11 @@
        custom: true,
        position: plot.legend,
        items: legends,
        itemName: {
          style: {
            fill: color,
          }
        }
      })
    }
@@ -347,7 +411,7 @@
      chart.tooltip(false)
    } else {
      chart.tooltip({
        shared: true
        shared: true,
      })
    }
@@ -424,7 +488,8 @@
  barrender = () => {
    const { card } = this.state
    let plot = {...card.plot, height: card.plot.height - 70}
    let plot = {...card.plot, height: card.plot.height - 80}
    let color = plot.color || 'rgba(0, 0, 0, 0.85)'
    let transfield = {}
    card.columns.forEach(col => {
@@ -466,30 +531,30 @@
  
      chart.data(dv.rows)
      // chart.axis(X_axis, {
      //   label: {
      //     style: {
      //       fill: '#ffffff',
      //     }
      //   },
      //   line: {
      //     style: {
      //       fill: '#ffffff',
      //     }
      //   }
      // })
      // chart.axis('value', {
      //   grid: {
      //     style: {
      //       fill: '#ffffff',
      //     }
      //   },
      //   label: {
      //     style: {
      //       fill: '#ffffff',
      //     }
      //   }
      // })
      chart.axis(X_axis, {
        label: {
          style: {
            fill: color,
          }
        },
        line: {
          style: {
            fill: color,
          }
        }
      })
      chart.axis('value', {
        grid: {
          style: {
            fill: color,
          }
        },
        label: {
          style: {
            fill: color,
          }
        }
      })
  
      chart.scale('value', {
        nice: true
@@ -500,11 +565,11 @@
      } else {
        chart.legend({
          position: plot.legend,
          // itemName: {
          //   style: {
          //     fill: '#ffffff',
          //   }
          // }
          itemName: {
            style: {
              fill: color,
            }
          }
        })
      }
  
@@ -639,6 +704,26 @@
    MKEmitter.emit('addButton', card.uuid, newcard)
  }
  changeStyle = () => {
    const { card } = this.state
    MKEmitter.emit('changeStyle', [card.uuid], ['font', 'background', 'border', 'padding', 'margin'], card.style)
  }
  getStyle = (comIds, style) => {
    const { card } = this.state
    if (comIds.length !== 1 || comIds[0] !== card.uuid) return
    let _card = {...card, style}
    this.setState({
      card: _card
    })
    this.props.updateConfig(_card)
  }
  render() {
    const { card } = this.state
@@ -655,6 +740,7 @@
              <Icon className="plus" title="添加搜索" onClick={this.addSearch} type="plus-circle" />
              <Icon className="plus" title="添加按钮" onClick={this.addButton} type="plus-square" />
              <ChartCompileForm config={card} dict={this.state.dict} plotchange={this.updateComponent}/>
              <Icon className="style" title="调整样式" onClick={this.changeStyle} type="font-colors" />
              <Icon className="close" title="delete" type="delete" onClick={() => this.props.deletecomponent(card.uuid)} />
              <SettingComponent config={card} updateConfig={this.updateComponent}/>
            </div>
@@ -670,7 +756,6 @@
          updateaction={this.updateComponent}
        />
        <div className="canvas" id={card.uuid}></div>
      </div>
    )
  }
src/menu/components/chart/antv-bar/index.scss
@@ -2,10 +2,13 @@
  position: relative;
  box-sizing: border-box;
  background: #ffffff;
  border-style: solid;
  border-width: 0;
  
  .canvas {
    margin: 0px;
    padding: 10px 15px;
    padding: 15px;
    letter-spacing: 0px;
  }
  .chart-header {
@@ -13,19 +16,26 @@
    height: 45px;
    border-bottom: 1px solid #e8e8e8;
    overflow: hidden;
    padding-right: 40px;
    padding-right: 35px;
    text-decoration: inherit;
    font-weight: inherit;
    font-style: inherit;
    >.anticon-tool {
      position: absolute;
      right: 0px;
      top: 0px;
      right: 1px;
      top: 1px;
      font-size: 16px;
      padding: 10px;
      padding: 5px;
      cursor: pointer;
      color: rgba(0, 0, 0, 0.85);
      background: #ffffff;
    }
    .chart-title {
      font-size: 16px;
      text-decoration: inherit;
      font-weight: inherit;
      font-style: inherit;
      float: left;
      line-height: 45px;
      margin-left: 10px;
@@ -37,6 +47,7 @@
    right: 0px;
    z-index: 4;
    padding-top: 10px;
    font-size: 16px;
  
    .ant-row .anticon-plus {
      float: right;
src/menu/components/tabs/antv-tabs/index.jsx
@@ -71,6 +71,7 @@
  componentDidMount () {
    MKEmitter.addListener('tabsChange', this.handleTabsChange)
    MKEmitter.addListener('submitStyle', this.getStyle)
  }
  /**
@@ -81,6 +82,27 @@
      return
    }
    MKEmitter.removeListener('tabsChange', this.handleTabsChange)
    MKEmitter.addListener('submitStyle', this.getStyle)
  }
  changeStyle = () => {
    const { tabs } = this.state
    MKEmitter.emit('changeStyle', [tabs.uuid], ['background', 'border', 'padding', 'margin'], tabs.style)
  }
  getStyle = (comIds, style) => {
    const { tabs } = this.state
    if (comIds.length !== 1 || comIds[0] !== tabs.uuid) return
    let _card = {...tabs, style}
    this.setState({
      tabs: _card
    })
    this.props.updateConfig(_card)
  }
  handleTabsChange = (parentId) => {
@@ -230,6 +252,7 @@
              <div className="mk-popover-control">
                <Icon className="plus" title="添加标签" type="plus" onClick={this.tabAdd} />
                <SettingComponent config={tabs} updateConfig={this.updateComponent} />
                <Icon className="style" title="调整样式" onClick={this.changeStyle} type="font-colors" />
                <Icon className="close" title="delete" type="delete" onClick={() => this.props.deletecomponent(tabs.uuid)} />
              </div>
            } trigger="hover">
src/menu/components/tabs/antv-tabs/index.scss
@@ -2,6 +2,8 @@
  position: relative;
  box-sizing: border-box;
  background: #ffffff;
  border-style: solid;
  border-width: 0;
  .ant-tabs-tabpane-active {
    min-height: 200px;
src/menu/modalconfig/index.jsx
New file
@@ -0,0 +1,1401 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import {connect} from 'react-redux'
import { is, fromJS } from 'immutable'
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, Popover } from 'antd'
import Api from '@/api'
import Utils from '@/utils/utils.js'
import zhCN from '@/locales/zh-CN/model.js'
import enUS from '@/locales/en-US/model.js'
import { getModalForm } from '@/templates/zshare/formconfig'
import { queryTableSql } from '@/utils/option.js'
import ModalForm from '@/templates/zshare/modalform'
import DragElement from '@/templates/modalconfig/dragelement'
import SourceElement from '@/templates/modalconfig/dragelement/source'
import SettingForm from '@/templates/modalconfig/settingform'
import GroupForm from '@/templates/modalconfig/groupform'
import EditCard from '@/templates/modalconfig/editcard'
import MenuForm from '@/templates/modalconfig/menuform'
import EditComponent from '@/templates/zshare/editcomponent'
import { BaseConfig, SearchItems } from '@/templates/modalconfig/source'
import './index.scss'
const { Panel } = Collapse
const { Option } = Select
const { confirm } = Modal
const CommonDict = localStorage.getItem('lang') !== 'en-US' ? zhCN : enUS
class ComModalConfig extends Component {
  static propTpyes = {
    menu: PropTypes.any,
    editTab: PropTypes.any,
    editSubTab: PropTypes.any,
    tabConfig: PropTypes.any,
    subTabConfig: PropTypes.any,
    btnTab: PropTypes.any,
    btnTabConfig: PropTypes.any,
    editAction: PropTypes.object,
    subConfig: PropTypes.any,
    handleView: PropTypes.func
  }
  state = {
    menu: null,            // 上级菜单,三级菜单或标签
    dict: CommonDict,      // 字典
    config: null,          // 页面配置,包括模板类型、模态框设置、添加表名、表单列表
    visible: false,        // 表单编辑模态框,显示控制
    modalType: null,       // 表单编辑类型,编辑或复制
    tableVisible: false,   // 数据表字段列表模态框,显示控制
    tableColumns: [],      // 表格字段名列表
    fields: null,          // 表单,可选字段(去重后)
    modalformlist: null,   // 基本信息表单字段
    formlist: null,        // 表单编辑模态框,可编辑字段
    card: null,            // 编辑元素
    menuloading: false,    // 菜单保存中
    closeloading: false,   // 菜单保存中
    settingVisible: false, // 全局配置模态框
    closeVisible: false,   // 关闭模态框
    tables: [],            // 可用表名
    selectedTables: [],    // 已选表名
    originConfig: null,    // 原始菜单
    groupVisible: false,   // 全局配置模态框
    curgroup: null,        // 当前组,新建或编辑
    sources: null,         // 表单类型
    sqlVerifing: false,    // sql验证
    openEdition: ''        // 编辑版本标记,防止多人操作
  }
  /**
   * @description 数据预处理
   * 1、按钮配置存在时使用按钮配置,不存在时使用默认配置(示例)
   * 2、模态框标题不存在时,使用按钮标题
   * 3、设置已选表
   * 4、设置按钮基本信息
   */
  UNSAFE_componentWillMount () {
    const {menu, editAction, tabConfig, subTabConfig, subConfig} = this.props
    let _config = ''
    let _tab = subTabConfig ? subTabConfig : tabConfig
    let _menu = { // 上级菜单是三级菜单或标签页
      type: _tab ? _tab.Template : menu.type,
      tables: _tab ? _tab.tables : menu.LongParam.tables,
      MenuID: _tab ? _tab.uuid : menu.MenuID,
      MenuNo: _tab ? _tab.tabNo : menu.MenuNo,
      MenuName: _tab ? _tab.tabName : menu.MenuName
    }
    if (subConfig) {
      _config = subConfig
    } else {
      _config = JSON.parse(JSON.stringify(BaseConfig))
    }
    if (!_config.setting.title) {
      _config.setting.title = editAction.label
    }
    // 主菜单已有选择的表名,模态框没有表名时,复制主菜单表名
    _config.tables = _config.tables.length === 0 ? _menu.tables : _config.tables
    let _source = JSON.parse(JSON.stringify(SearchItems))
    if (!!this.props.editTab) {
      _source.push({
        type: 'form',
        label: this.state.dict['header.form.linkMain'],
        subType: 'linkMain',
        url: ''
      })
    }
    this.setState({
      openEdition: editAction.open_edition || '',
      menu: _menu,
      source: _source,
      config: _config,
      selectedTables: _config.tables || [],
      originConfig: JSON.parse(JSON.stringify(_config)),
      modalformlist: [
        {
          type: 'text',
          key: 'supMenu',
          label: this.state.dict['model.super'] + this.state.dict['model.menu'],
          initVal: _menu.MenuName,
          required: true,
          readonly: true
        },
        {
          type: 'text',
          key: 'btnName',
          label: '按钮名称',
          initVal: editAction.label,
          required: true,
          readonly: true
        }
      ]
    })
  }
  /**
   * @description 获取数据表信息
   * 1、获取系统中全部表名
   * 2、根据已选表名,获取表格字段列表
   */
  componentDidMount () {
    let param = {
      func: 'sPC_Get_SelectedList',
      LText: queryTableSql,
      obj_name: 'data',
      arr_field: 'TbName,Remark'
    }
    param.LText = Utils.formatOptions(param.LText)
    param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
    param.secretkey = Utils.encrypt(param.LText, param.timestamp)
    param.open_key = Utils.encryptOpenKey(param.secretkey, param.timestamp) // 云端数据验证
    Api.getSystemConfig(param).then(res => {
      if (res.status) {
        this.setState({
          tables: res.data
        })
      } else {
        notification.warning({
          top: 92,
          message: res.message,
          duration: 10
        })
      }
    })
    let deffers = this.state.selectedTables.map(item => {
      return new Promise(resolve => {
        Api.getSystemConfig({func: 'sPC_Get_FieldName', TBName: item.TbName}).then(res => {
          res.TBName = item.TbName
          resolve(res)
        })
      })
    })
    // 获取字段后数据处理,根据类型分为text、number、datetime、date
    Promise.all(deffers).then(response => {
      let _columns = []
      response.forEach(res => {
        if (res.status) {
          let tabmsg = {
            tableName: res.TBName,
            columns: res.FDName.map(item => {
              let _type = item.FieldType.toLowerCase()
              let _decimal = 0
              if (/^nvarchar/.test(_type)) {
                _type = 'text'
              } else if (/^int/.test(_type)) {
                _type = 'number'
              } else if (/^decimal/.test(_type)) {
                _decimal = _type.split(',')[1]
                _decimal = parseInt(_decimal)
                _type = 'number'
              } else if (/^datetime/.test(_type)) {
                _type = 'datetime'
              } else if (/^date/.test(_type)) {
                _type = 'date'
              } else {
                _type = 'text'
              }
              return {
                field: item.FieldName,
                label: item.FieldDec,
                type: _type,
                decimal: _decimal
              }
            })
          }
          _columns.push(tabmsg)
        } else {
          notification.warning({
            top: 92,
            message: res.message,
            duration: 10
          })
        }
      })
      this.setState({
        tableColumns: _columns
      })
    })
  }
  /**
   * @description 组件销毁,清除state更新
   */
  componentWillUnmount () {
    this.setState = () => {
      return
    }
  }
  // 页面返回
  handleViewBack = () => {
    const {menu, editTab, editSubTab, tabConfig, subTabConfig, btnTab, btnTabConfig} = this.props
    let _view = (subTabConfig && subTabConfig.Template) || (tabConfig && tabConfig.Template) || menu.LongParam.Template
    let param = {
      editMenu: menu,
      editTab: editTab,
      tabConfig: tabConfig,
      editSubTab: editSubTab,
      subTabConfig: subTabConfig,
      btnTab: btnTab,
      btnTabConfig: btnTabConfig,
      editAction: null,
      subConfig: subTabConfig || tabConfig || null,
      tabview: _view
    }
    this.props.handleView(param)
  }
  /**
   * @description 表单变化
   * 1、表单拖拽添加时,检查是否存在示例表单,如存在则去除示例
   * 2、表单移动后,保存移动后的顺序
   * 3、新增表单时,直接打开编辑框
   */
  handleList = (list, group, elementId, newcard) => {
    let _config = JSON.parse(JSON.stringify(this.state.config))
    if (!group && !elementId) {
      // 没有分组时(拖拽添加)
      if (list.length > _config.fields.length) {
        _config.fields = list.filter(item => !item.origin)
        this.setState({
          config: _config
        }, () => {
          this.handleForm(newcard)
        })
      } else {
        _config.fields = list
        this.setState({config: _config})
      }
    } else if (group && !elementId) {
      // 存在分组时,拖拽添加
      if (list.length > group.sublist.length) {
        group.sublist = list
        _config.groups = _config.groups.map(item => {
          if (item.uuid === group.uuid) {
            return group
          } else {
            return item
          }
        })
        this.setState({
          config: _config
        }, () => {
          this.handleForm(newcard)
        })
      } else {
        group.sublist = list
        _config.groups = _config.groups.map(item => {
          if (item.uuid === group.uuid) {
            return group
          } else {
            return item
          }
        })
        this.setState({config: _config})
      }
    } else if (group && elementId) {
      // 修改已有元素的分组
      let element = null
      _config.groups.forEach(item => {
        item.sublist = item.sublist.filter(cell => {
          if (cell.uuid !== elementId) {
            return true
          } else {
            element = cell
            return false
          }
        })
      })
      group.sublist.push(element)
      _config.groups = _config.groups.map(item => {
        if (item.uuid === group.uuid) {
          return group
        } else {
          return item
        }
      })
      this.setState({
        config: _config
      })
    }
  }
  /**
   * @description 表单编辑
   * 1、显示编辑弹窗-visible
   * 2、保存编辑项-card
   * 3、设置编辑参数项-formlist
   */
  handleForm = (_card, type) => {
    const {menu, tabConfig, subTabConfig} = this.props
    let card = JSON.parse(JSON.stringify(_card))
    if (type === 'copy') {
      card.originUuid = card.uuid
      card.uuid = Utils.getuuid()
      card.focus = true
      // 复制到剪切板
      let oInput = document.createElement('input')
      let val = JSON.parse(JSON.stringify(card))
      val.copyType = 'form'
      val.uuid = Utils.getuuid()
      delete val.originUuid
      oInput.value = window.btoa(window.encodeURIComponent(JSON.stringify(val)))
      document.body.appendChild(oInput)
      oInput.select()
      document.execCommand('Copy')
      oInput.className = 'oInput'
      oInput.style.display = 'none'
      document.body.removeChild(oInput)
    }
    const { config } = this.state
    let _inputfields = []
    let _linkableFields = []
    let _linksupFields = [{
      value: '',
      text: '空'
    }]
    let _formfields = []
    // 设置下拉菜单可关联字段(上级与下级)
    if (config.groups.length > 0) {
      config.groups.forEach(group => {
        let sublist = group.sublist.filter(item => item.type === 'text' || item.type === 'number')
        _inputfields = [..._inputfields, ...sublist]
        let suplist = group.sublist.filter(item => item.type === 'select' || item.type === 'link')
        _formfields = [..._formfields, ...suplist]
      })
    } else {
      _inputfields = config.fields.filter(item => item.type === 'text' || item.type === 'number')
      _formfields = config.fields.filter(item => item.type === 'select' || item.type === 'link')
    }
    let uniq = new Map()
    uniq.set(card.field, true)
    _formfields.forEach(item => {
      if (item.field && !uniq.has(item.field)) {
        uniq.set(item.field, true)
        _linkableFields.push({
          value: item.field,
          text: item.label + ' (表单)'
        })
        _linksupFields.push({
          value: item.field,
          text: item.label
        })
      }
    })
    if (subTabConfig) {
      subTabConfig.columns.forEach(col => {
        if (col.field && !uniq.has(col.field)) {
          uniq.set(col.field, true)
          _linkableFields.push({
            value: col.field,
            text: col.label + ' (显示列)'
          })
        }
      })
    } else if (tabConfig) {
      tabConfig.columns.forEach(col => {
        if (col.field && !uniq.has(col.field)) {
          uniq.set(col.field, true)
          _linkableFields.push({
            value: col.field,
            text: col.label + ' (显示列)'
          })
        }
      })
    } else if (menu.LongParam) {
      menu.LongParam.columns.forEach(col => {
        if (col.field && !uniq.has(col.field)) {
          uniq.set(col.field, true)
          _linkableFields.push({
            value: col.field,
            text: col.label + ' (显示列)'
          })
        }
      })
    }
    if (card.linkSubField && card.linkSubField.length > 0) {
      let fields = _inputfields.map(item => item.field)
      card.linkSubField = card.linkSubField.filter(item => fields.includes(item))
    }
    let roleList = []
    if (this.props.sysRoles && this.props.sysRoles.length > 0) {
      roleList = this.props.sysRoles.map(role => {
        return {
          uuid: role.uuid,
          field: role.value,
          label: role.text
        }
      })
    }
    this.setState({
      visible: true,
      modalType: type,
      card: card,
      formlist: getModalForm(card, _inputfields, _linkableFields, _linksupFields, !!this.props.editTab, roleList)
    })
  }
  /**
   * @description 编辑后提交
   * 1、获取编辑后的表单信息
   * 2、去除可能存在的示例表单
   * 3、通过loading刷新
   */
  handleSubmit = () => {
    const { card, modalType } = this.state
    this.formRef.handleConfirm().then(res => {
      let _config = JSON.parse(JSON.stringify(this.state.config))
      let fieldrepet = false // 字段重复
      let labelrepet = false // 提示文字重复
      if (modalType === 'copy' && card.originUuid) {
        if (_config.groups.length > 0) {
          _config.groups = _config.groups.map(group => {
            let _index = null
            group.sublist.forEach((item, index) => {
              if (item.uuid === card.originUuid) {
                _index = index
              }
              if (item.uuid !== res.uuid && item.field === res.field) {
                fieldrepet = true
              } else if (item.uuid !== res.uuid && item.label === res.label) {
                labelrepet = true
              }
            })
            if (_index !== null) {
              group.sublist.splice(_index + 1, 0, res)
            }
            return group
          })
        } else {
          let _index = null
          _config.fields.forEach((item, index) => {
            if (item.uuid === card.originUuid) {
              _index = index
            }
            if (item.uuid !== res.uuid && item.field === res.field) {
              fieldrepet = true
            } else if (item.uuid !== res.uuid && item.label === res.label) {
              labelrepet = true
            }
          })
          _config.fields.splice(_index + 1, 0, res)
        }
      } else {
        if (_config.groups.length > 0) {
          _config.groups.forEach(group => {
            group.sublist = group.sublist.map(item => {
              if (item.uuid !== res.uuid && item.field === res.field) {
                fieldrepet = true
              } else if (item.uuid !== res.uuid && item.label === res.label) {
                labelrepet = true
              }
              if (item.uuid === res.uuid) {
                return res
              } else {
                return item
              }
            })
          })
        } else {
          _config.fields = _config.fields.map(item => {
            if (item.uuid !== res.uuid && item.field === res.field) {
              fieldrepet = true
            } else if (item.uuid !== res.uuid && item.label === res.label) {
              labelrepet = true
            }
            if (item.uuid === res.uuid) {
              return res
            } else {
              return item
            }
          })
        }
      }
      if (fieldrepet) {
        notification.warning({
          top: 92,
          message: '字段已存在!',
          duration: 10
        })
        return
      } else if (labelrepet) {
        notification.warning({
          top: 92,
          message: '名称已存在!',
          duration: 10
        })
        return
      }
      _config.fields = _config.fields.filter(item => !item.origin)
      if ((res.type === 'select' || res.type === 'multiselect' || res.type === 'link') && res.resourceType === '1' && /\s/.test(res.dataSource)) {
        this.setState({
          sqlVerifing: true
        })
        let param = {
          func: 's_debug_sql',
          LText: res.dataSource
        }
        param.LText = param.LText.replace(/@\$|\$@/ig, '')
        param.LText = Utils.formatOptions(param.LText)
        param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
        param.secretkey = Utils.encrypt(param.LText, param.timestamp)
        if (window.GLOB.mainSystemApi && res.database === 'sso') {
          param.rduri = window.GLOB.mainSystemApi
        }
        Api.getLocalConfig(param).then(result => {
          if (result.status) {
            this.setState({
              sqlVerifing: false,
              config: _config,
              modalType: null,
              card: null,
              visible: false
            })
          } else {
            this.setState({sqlVerifing: false})
            Modal.error({
              title: result.message
            })
          }
        })
      } else {
        this.setState({
          config: _config,
          modalType: null,
          card: null,
          visible: false
        })
      }
    })
  }
  /**
   * @description 表单删除并刷新
   */
  closeForm = (card) => {
    let _this = this
    confirm({
      content: `确定删除<<${card.label}>>吗?`,
      onOk() {
        let _config = JSON.parse(JSON.stringify(_this.state.config))
        if (_config.groups.length > 0) {
          _config.groups.forEach(group => {
            group.sublist = group.sublist.filter(item => !(item.uuid === card.uuid))
          })
        } else {
          _config.fields = _config.fields.filter(item => !(item.uuid === card.uuid))
        }
        _this.setState({
          config: _config,
        })
      },
      onCancel() {}
    })
  }
  submitConfig = () => {
    const { editAction } = this.props
    const { config, menu, openEdition } = this.state
    if ((!config.groups[0] && !config.fields[0]) || (config.fields[0] && config.fields[0].origin)) {
      notification.warning({
        top: 92,
        message: '请添加表单',
        duration: 10
      })
      return
    }
    let _LongParam = ''
    let _config = {...config, tables: this.state.selectedTables}
    try {
      _LongParam = window.btoa(window.encodeURIComponent(JSON.stringify(_config)))
    } catch (e) {
      notification.warning({
        top: 92,
        message: '编译错误',
        duration: 10
      })
      return
    }
    let param = {
      func: 'sPC_ButtonParam_AddUpt',
      ParentID: menu.MenuID,
      MenuID: editAction.uuid,
      MenuNo: menu.MenuNo,
      Template: 'Modal',
      MenuName: editAction.label,
      PageParam: JSON.stringify({Template: 'Modal'}),
      LongParam: _LongParam
    }
    if (openEdition) {
      param.open_edition = openEdition
    }
    if (this.state.closeVisible) {
      this.setState({
        closeloading: true
      })
    } else {
      this.setState({
        menuloading: true
      })
    }
    Api.getSystemConfig(param).then(response => {
      if (response.status) {
        this.setState({
          openEdition: response.open_edition || '',
          menuloading: false,
          closeloading: false,
          closeVisible: false,
          originConfig: _config,
          config: _config
        })
        notification.success({
          top: 92,
          message: '保存成功',
          duration: 2
        })
      } else {
        this.setState({
          closeloading: false,
          menuloading: false
        })
        notification.warning({
          top: 92,
          message: response.message,
          duration: 10
        })
      }
    })
  }
  cancelConfig = () => {
    const { config, originConfig } = this.state
    let _this = this
    let isOrigin = config.fields.filter(item => item.origin).length > 0
    if (isOrigin) {
      confirm({
        content: '尚未提交,确定放弃保存吗?',
        onOk() {
          _this.handleViewBack()
        },
        onCancel() {}
      })
    } else {
      if (!is(fromJS(config), fromJS(originConfig))) {
        this.setState({
          closeVisible: true
        })
      } else {
        this.handleViewBack()
      }
    }
  }
  /**
   * @description 通过表字段添加表单
   * 1、检查是否已选表名,为选时警告提示
   * 2、表字段名通过map去重
   * 3、检查表单中的已选字段,并标记已选
   */
  queryField = () => {
    const {selectedTables, tableColumns, config} = this.state
    if (selectedTables.length === 0) {
      notification.warning({
        top: 92,
        message: '请选择表名!',
        duration: 10
      })
      return
    }
    let columns = new Map()
    tableColumns.forEach(table => {
      table.columns.forEach(column => {
        columns.set(column.field, column)
      })
    })
    if (config.groups.length > 1) {
      config.groups.forEach(group => {
        group.sublist.forEach(item => {
          if (columns.has(item.field)) {
            columns.set(item.field, {...item, selected: true})
          }
        })
      })
    } else {
      config.fields.forEach(item => {
        if (columns.has(item.field)) {
          columns.set(item.field, {...item, selected: true})
        }
      })
    }
    this.setState({
      tableVisible: true,
      fields: [...columns.values()]
    })
  }
  /**
   * @description 选择字段后提交
   * 1、没有可选字段时,直接关闭
   * 2、获取已选字段
   * 3、与已有字段对比
   * 4、添加新增字段
   */
  addFieldSubmit = () => {
    if (!this.state.fields || this.state.fields.length === 0) {
      this.setState({
        tableVisible: false
      })
    }
    let _config = JSON.parse(JSON.stringify(this.state.config))
    let cards = this.refs.searchcard.state.selectCards
    let columns = new Map()
    cards.forEach(card => {
      columns.set(card.field, card)
    })
    if (_config.groups.length > 1) {
      _config.groups.forEach(group => {
        let items = []
        group.sublist.forEach(item => {
          if (columns.has(item.field)) {
            let cell = columns.get(item.field)
            if (cell.selected && cell.type === item.type) { // 数据选择状态及类型未修改时,直接添加
              items.push(item)
            } else if (cell.selected) {                     // 数据类型修改时,重置类型及初始值
              item.type = cell.type
              item.initval = ''
              items.push(item)
            }
            columns.delete(item.field)
          } else if (!item.origin) {                        // 过滤示例项
            items.push(item)
          }
        })
        group.sublist = items
      })
      let _columns = [...columns.values()]
      let _additems = _columns.map(item => { // 循环添加新增字段
        return {
          uuid: Utils.getuuid(),
          label: item.label,
          field: item.field,
          initval: '',
          type: item.type,
          resourceType: '0',
          setAll: 'false',
          options: [],
          dataSource: '',
          linkField: '',
          valueField: '',
          valueText: '',
          orderBy: '',
          orderType: 'asc',
          decimal: 0,
          min: '',
          max: '',
          readonly: 'false',
          required: 'true'
        }
      })
      _config.groups[_config.groups.length - 1].sublist = [..._config.groups[_config.groups.length - 1].sublist, ..._additems]
    } else {
      let items = []
      _config.fields.forEach(item => {
        if (columns.has(item.field)) {
          let cell = columns.get(item.field)
          if (cell.selected && cell.type === item.type) { // 数据选择状态及类型未修改时,直接添加
            items.push(item)
          } else if (cell.selected) {                     // 数据类型修改时,重置类型及初始值
            item.type = cell.type
            item.initval = ''
            items.push(item)
          }
          columns.delete(item.field)
        } else if (!item.origin) {                        // 过滤示例项
          items.push(item)
        }
      })
      let _columns = [...columns.values()]
      _columns.forEach(item => { // 循环添加新增字段
        if (item.selected) {
          let newcard = {
            uuid: Utils.getuuid(),
            label: item.label,
            field: item.field,
            initval: '',
            type: item.type,
            resourceType: '0',
            setAll: 'false',
            options: [],
            dataSource: '',
            linkField: '',
            valueField: '',
            valueText: '',
            orderBy: '',
            orderType: 'asc',
            readonly: 'false',
            required: 'true'
          }
          items.push(newcard)
        }
      })
      _config.fields = items
    }
    this.setState({
      config: _config
    })
    notification.success({
      top: 92,
      message: '添加成功',
      duration: 2
    })
  }
  /**
   * @description 添加表名
   * 1、获取表信息
   * 2、检验是否已经添加,已添加时跳过
   * 3、通过表名获取字段集,并设置数据类型
   */
  onTableChange = (value) => {
    const {tables, selectedTables, tableColumns} = this.state
    let _table = tables.filter(item => item.TbName === value)[0]
    let isSelected = !!selectedTables.filter(cell => cell.TbName === value)[0]
    if (isSelected) return
    this.setState({
      selectedTables: [...selectedTables, _table]
    })
    Api.getSystemConfig({func: 'sPC_Get_FieldName', TBName: value}).then(res => {
      if (res.status) {
        let tabmsg = {
          tableName: _table.name,
          columns: res.FDName.map(item => {
            let _type = item.FieldType.toLowerCase()
            let _decimal = 0
            if (/^nvarchar/.test(_type)) {
              _type = 'text'
            } else if (/^int/.test(_type)) {
              _type = 'number'
            } else if (/^decimal/.test(_type)) {
              _decimal = _type.split(',')[1]
              _decimal = parseInt(_decimal)
              _type = 'number'
            } else if (/^datetime/.test(_type)) {
              _type = 'datetime'
            } else if (/^date/.test(_type)) {
              _type = 'date'
            } else {
              _type = 'text'
            }
            return {
              field: item.FieldName,
              label: item.FieldDec,
              type: _type,
              decimal: _decimal
            }
          })
        }
        this.setState({
          tableColumns: [...tableColumns, tabmsg]
        })
      } else {
        notification.warning({
          top: 92,
          message: res.message,
          duration: 10
        })
      }
    })
  }
  /**
   * @description 删除表名,删除对应字段集
   */
  deleteTable = (table) => {
    const {selectedTables, tableColumns} = this.state
    this.setState({
      selectedTables: selectedTables.filter(item => item.TbName !== table.TbName),
      tableColumns: tableColumns.filter(item => item.tableName !== table.TbName)
    })
  }
  /**
   * @description 全局设置模态框
   */
  changeSetting = () => {
    this.setState({
      settingVisible: true
    })
  }
  /**
   * @description 保存全局设置
   */
  settingSave = () => {
    const {config} = this.state
    this.settingRef.handleConfirm().then(res => {
      this.setState({
        config: {...config, setting: res},
        settingVisible: false
      })
    })
  }
  handleGroup = (group) => {
    let curgroup = ''
    if (group) {
      curgroup = group
    } else {
      curgroup = {
        isnew: true,
        label: '',
        default: false,
        uuid: Utils.getuuid(),
        sublist: []
      }
    }
    this.setState({
      groupVisible: true,
      curgroup: curgroup
    })
  }
  closeGroup = (group) => {
    let _this = this
    confirm({
      content: `确定删除分组<<${group.label}>>吗?`,
      onOk() {
        let _config = JSON.parse(JSON.stringify(_this.state.config))
        _config.groups = _config.groups.filter(item => !(item.uuid === group.uuid))
        let _length = _config.groups.length
        if (_length === 1) {
          _config.fields = [...group.sublist, ..._config.groups[0].sublist]
          _config.groups = []
        } else {
          _config.groups[_length - 1].sublist = [...group.sublist, ..._config.groups[_length - 1].sublist]
        }
        _this.setState({
          config: _config
        })
      },
      onCancel() {}
    })
  }
  handleGroupSave = () => {
    let _group = JSON.parse(JSON.stringify(this.state.curgroup))
    let config = JSON.parse(JSON.stringify(this.state.config))
    this.groupRef.handleConfirm().then(res => {
      _group = {..._group, ...res.target}
      if (_group.isnew) {
        delete _group.isnew
        config.groups.unshift(_group)
        if (config.groups.length > 1) {
          config.groups = config.groups.map(item => {
            if (item.default) {
              return res.default
            } else {
              return item
            }
          })
        } else {
          config.groups.push(res.default)
        }
      } else {
        config.groups = config.groups.map(item => {
          if (item.uuid === _group.uuid) {
            return _group
          } else if (item.default) {
            return res.default
          } else {
            return item
          }
        })
      }
      config.fields = []
      config.groups = config.groups.sort((a, b) => {
        return a.sort - b.sort
      })
      this.setState({
        groupVisible: false,
        curgroup: '',
        config: config
      })
    })
  }
  editModalCancel = () => {
    const { config, card } = this.state
    if (card.focus) {
      let _config = null
      if (config.groups.length > 0) {
        let _groups = config.groups.map(group => {
          group.sublist = group.sublist.filter(item => item.uuid !== card.uuid)
          return group
        })
        _config = {...config, groups: _groups}
      } else {
        let _fields = config.fields.filter(item => item.uuid !== card.uuid)
        _config = {...config, fields: _fields}
      }
      this.setState({
        card: null,
        config: _config,
        visible: false
      })
    } else {
      this.setState({
        card: null,
        visible: false
      })
    }
  }
  /**
   * @description 编辑功能完成更新,包括解冻按钮、粘贴、替换等
   */
  updateConfig = (res) => {
    if (res.type === 'paste') {
      this.setState({
        config: res.content
      })
    }
  }
  render () {
    const { config, source } = this.state
    return (
      <div className="modal-form-board">
        <DndProvider backend={HTML5Backend}>
          <div className="tools">
            <Collapse accordion defaultActiveKey="1" bordered={false}>
              <Panel header={this.state.dict['header.menu.basedata']} key="0" id="modal-basedata">
                <MenuForm
                  dict={this.state.dict}
                  formlist={this.state.modalformlist}
                />
                <div className="ant-col ant-form-item-label">
                  <label title={this.state.dict['header.menu.table.add']}>
                    {this.state.dict['header.menu.table.add']}
                  </label>
                </div>
                <Select
                  showSearch
                  showArrow={false}
                  className="tables"
                  style={{ width: '100%' }}
                  optionFilterProp="children"
                  value={this.state.dict['header.menu.table.placeholder']}
                  onChange={this.onTableChange}
                  getPopupContainer={() => document.getElementById('modal-basedata')}
                  filterOption={(input, option) => {
                    return option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0
                  }}
                >
                  {this.state.tables.map((table, index) => (
                    <Option key={index} title={table.TbName} value={table.TbName}>{table.Remark}</Option>
                  ))}
                </Select>
                {this.state.selectedTables.length > 0 && <List
                  size="small"
                  bordered
                  dataSource={this.state.selectedTables}
                  renderItem={(item, index) => <List.Item key={index} title={item.Remark + ' (' + item.TbName + ')'}>
                    {item.Remark + ' (' + item.TbName + ')'}
                    <Icon type="close" onClick={() => this.deleteTable(item)}/>
                    <div className="bottom-mask"></div>
                  </List.Item>}
                />}
              </Panel>
              <Panel header={this.state.dict['header.menu.form']} key="1">
                <div className="search-element">
                  {source.map((item, index) => {
                    return (<SourceElement key={index} content={item}/>)
                  })}
                </div>
                <Button type="primary" block onClick={() => this.queryField()}>{this.state.dict['header.menu.form.add']}</Button>
                <Button type="primary" block onClick={() => this.handleGroup()}>{this.state.dict['header.menu.group.add']}</Button>
              </Panel>
            </Collapse>
          </div>
          <div className="setting">
            <Card title={this.state.dict['header.menu.form.configurable']} bordered={false} extra={
              <div>
                <EditComponent dict={this.state.dict} type="form" config={this.state.config} refresh={this.updateConfig}/>
                <Button type="primary" onClick={this.submitConfig} loading={this.state.menuloading}>{this.state.dict['model.save']}</Button>
                <Button onClick={this.cancelConfig}>{this.state.dict['model.back']}</Button>
              </div>
            } style={{ width: '100%' }}>
              <Icon type="setting" onClick={this.changeSetting} />
              <div className="ant-modal-content" style={{width: config.setting.width + '%'}}>
                <button type="button" className="ant-modal-close">
                  <span className="ant-modal-close-x"><Icon type="close"/></span>
                </button>
                <div className="ant-modal-header">
                  <div className="ant-modal-title">{config.setting.title}</div>
                </div>
                <div className="ant-modal-body">
                  <div className="modal-form">
                    {config.groups.length > 0 &&
                      config.groups.map(group => {
                        return (
                          <div key={group.uuid}>
                            <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}
                              setting={config.setting}
                              placeholder={this.state.dict['header.form.modal.placeholder']}
                              handleList={this.handleList}
                              handleForm={this.handleForm}
                              closeForm={this.closeForm}
                            />
                          </div>
                        )
                      })
                    }
                    {config.groups.length === 0 ?
                      <DragElement
                        list={config.fields}
                        setting={config.setting}
                        placeholder={this.state.dict['header.form.modal.placeholder']}
                        handleList={this.handleList}
                        handleForm={this.handleForm}
                        closeForm={this.closeForm}
                      /> : null
                    }
                  </div>
                </div>
                <div className="ant-modal-footer">
                  <div>
                    <button type="button" className="ant-btn">
                      <span>{this.state.dict['model.cancel']}</span>
                    </button>
                    <button type="button" className="ant-btn ant-btn-primary">
                      <span>{this.state.dict['model.confirm']}</span>
                    </button>
                  </div>
                  <div className="action-mask"></div>
                </div>
              </div>
            </Card>
          </div>
        </DndProvider>
        <Modal
          title={this.state.modalType !== 'copy' ? this.state.dict['model.edit'] : this.state.dict['header.modal.form.copy']}
          visible={this.state.visible}
          width={700}
          onCancel={this.editModalCancel}
          onOk={this.handleSubmit}
          confirmLoading={this.state.sqlVerifing}
          destroyOnClose
        >
          {<ModalForm
            dict={this.state.dict}
            card={this.state.card}
            formlist={this.state.formlist}
            inputSubmit={this.handleSubmit}
            wrappedComponentRef={(inst) => this.formRef = inst}
          />}
        </Modal>
        <Modal
          wrapClassName="modal-fields"
          title={this.state.dict['model.edit']}
          visible={this.state.tableVisible}
          width={'65vw'}
          maskClosable={false}
          style={{minWidth: '900px', maxWidth: '1200px'}}
          onOk={this.addFieldSubmit}
          cancelText={this.state.dict['model.close']}
          onCancel={() => { this.setState({ tableVisible: false }) }}
          destroyOnClose
        >
          {this.state.fields && this.state.fields.length > 0 ?
            <EditCard data={this.state.fields} ref="searchcard" type="search" /> : null
          }
          {(!this.state.fields || this.state.fields.length === 0) &&
            <Empty />
          }
        </Modal>
        <Modal
          title={this.state.dict['model.edit']}
          visible={this.state.settingVisible}
          width={700}
          maskClosable={false}
          onOk={this.settingSave}
          onCancel={() => { this.setState({ settingVisible: false }) }}
          destroyOnClose
        >
          <SettingForm
            config={config}
            dict={this.state.dict}
            isSubTab={!!this.props.editTab}
            inputSubmit={this.settingSave}
            wrappedComponentRef={(inst) => this.settingRef = inst}
          />
        </Modal>
        <Modal
          bodyStyle={{textAlign: 'center', color: '#000000', fontSize: '16px'}}
          closable={false}
          maskClosable={false}
          visible={this.state.closeVisible}
          onCancel={() => { this.setState({closeVisible: false}) }}
          footer={[
            <Button key="save" className="mk-btn mk-green" loading={this.state.closeloading} onClick={this.submitConfig}>{this.state.dict['model.save']}</Button>,
            <Button key="confirm" className="mk-btn mk-yellow" onClick={this.handleViewBack}>{this.state.dict['model.notsave']}</Button>,
            <Button key="cancel" onClick={() => { this.setState({closeVisible: false}) }}>{this.state.dict['model.cancel']}</Button>
          ]}
          destroyOnClose
        >
          {this.state.dict['header.menu.config.placeholder']}
        </Modal>
        <Modal
          title={this.state.dict['header.menu.group.manage']}
          visible={this.state.groupVisible}
          width={700}
          maskClosable={false}
          onOk={this.handleGroupSave}
          onCancel={() => { this.setState({ groupVisible: false }) }}
          destroyOnClose
        >
          <GroupForm
            config={config}
            dict={this.state.dict}
            group={this.state.curgroup}
            inputSubmit={this.handleGroupSave}
            wrappedComponentRef={(inst) => this.groupRef = inst}
          />
        </Modal>
      </div>
    )
  }
}
const mapStateToProps = (state) => {
  return {
    sysRoles: state.sysRoles
  }
}
const mapDispatchToProps = () => {
  return {}
}
export default connect(mapStateToProps, mapDispatchToProps)(ComModalConfig)
src/menu/modalconfig/index.scss
New file
@@ -0,0 +1,295 @@
.modal-form-board {
  position: fixed;
  z-index: 1070;
  padding-top: 48px;
  top: 0px;
  left: 0px;
  right: 0px;
  bottom: 0px;
  background: rgba(0, 0, 0, 0.35);
  display: flex;
  .tools {
    flex: 1;
    background: #ffffff;
    border-right: 1px solid #d9d9d9;
    height: 100%;
    overflow-y: auto;
    padding-bottom: 30px;
    .ant-collapse-item {
      border: 0;
    }
    .ant-input-search {
      margin-top: 10px;
    }
    .ant-collapse-item.ant-collapse-item-active {
      border-bottom: 1px solid #d9d9d9;
    }
    .ant-collapse .ant-collapse-header {
      padding: 11px 16px 10px 40px;
      border-bottom: 1px solid #d9d9d9;
      background: #1890ff;
      color: #ffffff;
    }
    .ant-collapse-content-box {
      .ant-form-item {
        margin-bottom: 10px;
        .ant-form-item-label {
          text-align: left;
          height: 25px;
          line-height: 25px;
        }
      }
      .ant-btn {
        margin-bottom: 10px;
      }
    }
    .search-element {
      padding-top: 10px;
      li {
        padding: 0px 16px 10px;
        div {
          cursor: move;
        }
      }
    }
    .tables {
      .ant-select-selection-selected-value {
        opacity: 0.4!important;
      }
    }
    .ant-list {
      margin-top: 20px;
      .ant-list-item {
        display: -webkit-box;
        padding-right: 20px;
        position: relative;
        padding-left: 5px;
        overflow: hidden;
        text-overflow: ellipsis;
        -webkit-line-clamp: 2;
        -webkit-box-orient: vertical;
        width: 100%;
        .anticon {
          position: absolute;
          top: 0px;
          right: 0px;
          padding: 3px 3px 10px 10px;
          cursor: pointer;
        }
        .bottom-mask {
          position: absolute;
          width: 100%;
          height: 8px;
          bottom: 0;
          left: 0;
          background: #ffffff;
          border-radius: 8px;
        }
      }
    }
  }
  .tools::-webkit-scrollbar {
    width: 4px;
  }
  .tools::-webkit-scrollbar-thumb {
    border-radius: 5px;
    box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.08);
    background: rgba(0, 0, 0, 0.08);
  }
  .tools::-webkit-scrollbar-track {
    box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.05);
    border-radius: 3px;
    border: 1px solid rgba(0, 0, 0, 0.07);
    background: rgba(0, 0, 0, 0);
  }
  .setting {
    position: relative;
    width: calc(100vw - 235px);
    height: 100%;
    overflow-y: hidden;
    background: #ffffff;
    .ant-card-head {
      min-height: 44px;
    }
    .ant-card-head-title {
      padding: 5px 0;
      color: #1890ff;
    }
    .ant-card-extra {
      padding: 5px 0;
      button {
        margin-left: 20px;
      }
    }
    .ant-card-body {
      position: relative;
      padding: 0;
      .ant-modal-content {
        max-width: 95%;
        margin: 0 auto;
        margin-top: 30px;
        .ant-modal-header {
          position: relative;
          z-index: 10;
          background: transparent;
        }
        .ant-modal-close {
          opacity: 0.3;
        }
        .ant-modal-footer {
          position: relative;
          button {
            opacity: 0.3;
          }
        }
        .action-mask {
          position: absolute;
          top: 0px;
          left: 0px;
          right: 0px;
          bottom: 0px;
        }
      }
      .modal-form {
        padding: 0px 24px;
        min-height: 87px;
        .group-title {
          position: relative;
          min-height: 22px;
          margin-bottom: 10px;
          padding-top: 10px;
          border-bottom: 1px solid #e8e8e8;
          span {
            padding: 0 5px 5px;
          }
        }
        > .ant-row {
          min-height: 120px;
        }
        .ant-row .ant-col-6 {
          padding: 0 12px!important;
        }
        .ant-row.ant-form-item .ant-col {
          padding: 0;
        }
        .textarea2, .textarea4 {
          padding-left: 7px;
        }
        .page-card {
          position: relative;
          background: #ffffff;
          border-radius: 2px;
          margin-bottom: 15px;
          .ant-form-item {
            cursor: move;
            display: flex;
            margin-bottom: 0px;
            .ant-form-item-label {
              overflow: visible;
              position: relative;
              height: 40px;
              label {
                width: 100%;
                cursor: move;
                overflow: hidden;
                display: inline-block;
                text-overflow: ellipsis;
                white-space: nowrap;
              }
            }
            .ant-form-item-control-wrapper {
              .ant-select {
                width: 100%;
                margin-top: 4px;
              }
              .ant-calendar-picker {
                width: 100%;
                margin-top: 4px;
              }
              .ant-input-number {
                width: 100%;
                margin-top: 4px;
              }
              .input-mask {
                position: absolute;
                top: 0;
                left: 0;
                right: 0;
                bottom: 0;
                opacity: 0;
              }
            }
            .ant-col-cuslabel {
              width: 10.5%;
            }
            .ant-col-cuswrap {
              width: 89.5%;
            }
          }
        }
        .ant-calendar-picker {
          min-width: 100px!important;
        }
      }
      > .anticon-setting {
        position: absolute;
        font-size: 16px;
        right: 15px;
        top: 10px;
      }
      .paste-Icon {
        position: absolute;
        font-size: 16px;
        right: 15px;
        top: 65px;
      }
    }
  }
  .setting:hover {
    overflow-y: auto;
  }
  .setting::-webkit-scrollbar {
    width: 7px;
  }
  .setting::-webkit-scrollbar-thumb {
    border-radius: 5px;
    box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.13);
    background: rgba(0, 0, 0, 0.13);
  }
  .setting::-webkit-scrollbar-track {
    box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.05);
    border-radius: 3px;
    border: 1px solid rgba(0, 0, 0, 0.07);
    background: rgba(0, 0, 0, 0);
  }
}
.modal-fields {
  .ant-modal {
    top: 50px;
    padding-bottom: 5px;
    .ant-modal-body {
      max-height: calc(100vh - 190px);
      overflow-y: auto;
      .ant-empty {
        margin: 15vh 8px;
      }
    }
    .ant-modal-body::-webkit-scrollbar {
      width: 7px;
    }
    .ant-modal-body::-webkit-scrollbar-thumb {
      border-radius: 5px;
      box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.13);
      background: rgba(0, 0, 0, 0.13);
    }
    .ant-modal-body::-webkit-scrollbar-track {
      box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.05);
      border-radius: 3px;
      border: 1px solid rgba(0, 0, 0, 0.07);
      background: rgba(0, 0, 0, 0);
    }
  }
}
src/menu/searchcomponent/index.jsx
@@ -21,7 +21,6 @@
class SearchComponent extends Component {
  static propTpyes = {
    config: PropTypes.object,        // 配置信息
    // optionLibs: PropTypes.any,       // 下拉字典
    updatesearch: PropTypes.func     // 更新
  }
src/tabviews/commontable/index.jsx
@@ -908,6 +908,7 @@
  }
  render() {
    const { menuType } = this.props
    const { BID, setting, searchlist, pageSize, actions, columns, loadingview, viewlost, pickup, config, triggerBtn, userConfig, tabActive, chartId, search, selectedData } = this.state
    return (
@@ -1068,7 +1069,7 @@
            </Tabs>)
          )
        }
        {options.sysType !== 'cloud' ? <Button
        {options.sysType !== 'cloud' && menuType !== 'HS' ? <Button
          icon="copy"
          shape="circle"
          className="common-table-copy"
src/tabviews/custom/components/card/data-card/index.scss
@@ -23,6 +23,7 @@
  .prev-page.disabled {
    img {
      cursor: not-allowed;
      opacity: 0.4;
    }
  }
  .card-row-list::after {
src/tabviews/custom/components/chart/antv-bar-line/index.jsx
@@ -102,8 +102,11 @@
    }
    let showHeader = false
    if (config.plot.title || _config.plot.datatype === 'statistics') {
    if (config.plot.title || _config.plot.datatype === 'statistics' || config.search.length > 0) {
      showHeader = true
      _config.plot.height = _config.plot.height - 80
    } else {
      _config.plot.height = _config.plot.height - 30
    }
    this.setState({
@@ -1077,7 +1080,7 @@
              }
            })}
          </div>
          <div className={'canvas' + (empty ? ' empty' : '')} style={{minHeight: plot.height ? plot.height : 400}} id={this.state.chartId}></div>
          <div className={'canvas' + (empty ? ' empty' : '')} id={this.state.chartId}></div>
        </div>
        {empty ? <Empty description={false}/> : null}
      </div>
src/tabviews/custom/components/chart/antv-bar-line/index.scss
@@ -1,16 +1,24 @@
.custom-line-chart-plot-box {
  background: #ffffff;
  border-style: solid;
  border-width: 0;
  > .chart-header {
    height: 45px;
    border-bottom: 1px solid #e8e8e8;
    overflow: hidden;
    text-decoration: inherit;
    font-weight: inherit;
    font-style: inherit;
    .chart-title {
      font-size: 16px;
      // font-size: 16px;
      float: left;
      line-height: 45px;
      margin-left: 10px;
      text-decoration: inherit;
      font-weight: inherit;
      font-style: inherit;
    }
  }
  
@@ -31,7 +39,8 @@
  .canvas {
    margin: 0;
    // border: 1px solid #e8e8e8;
    padding: 25px 15px;
    padding: 15px;
    letter-spacing: 0px;
  }
  .canvas.empty {
    div {
src/tabviews/custom/components/tabs/antv-tabs/index.jsx
@@ -54,7 +54,7 @@
    const { tabs } = this.state
    return (
      <div className="menu-antv-tabs-wrap">
      <div className="menu-antv-tabs-wrap" style={tabs.style}>
        <Tabs defaultActiveKey="1" tabPosition={tabs.setting.position} type={tabs.setting.tabStyle}>
          {tabs.subtabs.map(tab => (
            <TabPane tab={<span>{tab.icon ? <Icon type={tab.icon} /> : null}{tab.label}</span>} key={tab.uuid}>
src/tabviews/custom/components/tabs/antv-tabs/index.scss
@@ -2,4 +2,6 @@
  position: relative;
  box-sizing: border-box;
  background: #ffffff;
  border-style: solid;
  border-width: 0;
}
src/tabviews/zshare/normalTable/index.jsx
@@ -856,10 +856,6 @@
    let selects = this.props.data.filter((item, _index) => selectedRowKeys.includes(_index))
    // selectedRowKeys.forEach(item => {
    //   selects.push(this.props.data[item])
    // })
    this.props.chgSelectData(selects)
  }
@@ -893,9 +889,6 @@
    }
    let selects = this.props.data.filter((item, _index) => newkeys.includes(_index))
    // newkeys.forEach(item => {
    //   selects.push(this.props.data[item])
    // })
    
    this.props.chgSelectData(selects)
  }
@@ -1022,7 +1015,7 @@
        {offset && <Affix offsetTop={offset} className="fix-header">
          <Table
            size="middle"
            bordered={true}
            bordered={setting.bordered !== 'false'}
            rowSelection={rowSelection}
            columns={this.state.columns.map(column => {
              return {
@@ -1036,7 +1029,7 @@
        </Affix>}
        <Table
          size="middle"
          bordered={true}
          bordered={setting.bordered !== 'false'}
          rowSelection={rowSelection}
          columns={this.state.columns}
          dataSource={_data}
src/templates/calendarconfig/index.jsx
@@ -34,7 +34,6 @@
class SubTableConfig extends Component {
  static propTpyes = {
    menu: PropTypes.any,
    optionLibs: PropTypes.any,
    reloadmenu: PropTypes.func,
    handleView: PropTypes.func
  }
@@ -52,7 +51,6 @@
    closeVisible: false,     // 关闭模态框
    originConfig: null,      // 原配置
    tabviews: [],            // 所有标签页
    optionLibs: null,        // 自定义下拉选项库
    activeKey: '0',          // 默认展开基本信息
    pasteContent: null,      // 粘贴内容
    openEdition: '',         // 编辑版本标记,防止多人操作
@@ -65,7 +63,7 @@
   * 2、设置操作类型、原始菜单信息(每次保存后重置)、已使用表及基本信息表单
   */
  UNSAFE_componentWillMount () {
    const { menu, optionLibs } = this.props
    const { menu } = this.props
    let _LongParam = menu.LongParam
    let _config = ''
@@ -74,21 +72,6 @@
      _config.isAdd = true
    } else {
      _config = _LongParam
      _config.search.forEach(item => {
        if (
          (item.type === 'select' || item.type === 'multiselect' || item.type === 'link') &&
          item.resourceType === '0' &&
          item.options && item.options.length > 0
        ) {
          optionLibs.set(menu.MenuID + item.uuid, {
            uuid: menu.MenuID + item.uuid,
            label: item.label,
            parname: menu.MenuName,
            type: 'search',
            options: item.options
          })
        }
      })
    }
    if (_config.type === 'user') {
@@ -112,7 +95,6 @@
    this.setState({
      openEdition: menu.open_edition || '',
      optionLibs: optionLibs,
      activeKey: menu.activeKey || '0',
      config: _config,
      originMenu: fromJS(_config).toJS(),
@@ -234,7 +216,6 @@
  handleViewBack = () => {
    let param = {
      editMenu: null,
      optionLibs: null,
      editTab: null,
      tabConfig: null,
      subTabConfig: null,
@@ -533,7 +514,7 @@
   */
  setSubConfig = () => {
    const { menu } = this.props
    const { config, originMenu, optionLibs, activeKey, openEdition } = this.state
    const { config, originMenu, activeKey, openEdition } = this.state
    if (config.isAdd) { // 新建菜单,提示菜单尚未保存
      notification.warning({
@@ -579,7 +560,6 @@
      _Menu.open_edition = openEdition  // 更新版本号
      let param = {
        optionLibs: optionLibs,
        editMenu: _Menu,
        editTab: fromJS(config.tab).toJS(),
        tabConfig: null,
@@ -720,12 +700,10 @@
  /**
   * @description 更新搜索条件配置信息
   */
  updatesearch = (config, options) => {
    const { optionLibs } = this.state
  updatesearch = (config) => {
    this.setState({
      config: config,
      optionLibs: options || optionLibs
      config: config
    })
  }
@@ -825,7 +803,6 @@
                config={config}
                pasteContent={this.state.pasteContent}
                sysRoles={this.props.sysRoles}
                optionLibs={this.state.optionLibs}
                updatesearch={this.updatesearch}
              />
              <div className="calendar-wrap">
src/templates/comtableconfig/index.jsx
@@ -37,7 +37,6 @@
class ComTableConfig extends Component {
  static propTpyes = {
    menu: PropTypes.any,
    optionLibs: PropTypes.any,
    reloadmenu: PropTypes.func,
    handleView: PropTypes.func
  }
@@ -57,7 +56,6 @@
    delActions: [],          // 删除按钮列表
    copyActions: [],         // 复制按钮组
    tabviews: [],            // 所有标签页
    optionLibs: null,        // 自定义下拉选项库
    thawButtons: [],         // 已选择要解冻的按钮
    activeKey: '0',          // 默认展开基本信息
    chartview: null,         // 当前视图
@@ -71,7 +69,7 @@
   * 2、设置操作类型、原始菜单信息(每次保存后重置)、已使用表及基本信息表单
   */
  UNSAFE_componentWillMount () {
    const { menu, optionLibs } = this.props
    const { menu } = this.props
    let _LongParam = menu.LongParam
    let _config = ''
@@ -83,21 +81,6 @@
      _config.isAdd = true
    } else {
      _config = _LongParam
      _config.search.forEach(item => {
        if (
          (item.type === 'select' || item.type === 'multiselect' || item.type === 'link') &&
          item.resourceType === '0' &&
          item.options && item.options.length > 0
        ) {
          optionLibs.set(menu.MenuID + item.uuid, {
            uuid: menu.MenuID + item.uuid,
            label: item.label,
            parname: menu.MenuName,
            type: 'search',
            options: item.options
          })
        }
      })
    }
    // 页面配置中保留菜单信息,只用于数据传递
@@ -157,7 +140,6 @@
      config: _config,
      openEdition: menu.open_edition || '',
      activeKey: menu.activeKey || '0',
      optionLibs: optionLibs,
      originActions: _oriActions,
      originMenu: fromJS(_config).toJS()
    })
@@ -882,7 +864,7 @@
   */
  setSubConfig = (item, type) => {
    const { menu } = this.props
    const { config, originMenu, optionLibs, activeKey, openEdition } = this.state
    const { config, originMenu, activeKey, openEdition } = this.state
    if (config.isAdd) { // 新建菜单,提示菜单尚未保存
      notification.warning({
@@ -948,7 +930,6 @@
      _Menu.open_edition = openEdition  // 更新版本号
      let param = {
        optionLibs: optionLibs,
        editMenu: _Menu,
        editTab: !isbutton ? item : '',
        tabConfig: null,
@@ -1176,12 +1157,10 @@
  /**
   * @description 更新搜索条件配置信息
   */
  updatesearch = (config, options) => {
    const { optionLibs } = this.state
  updatesearch = (config) => {
    this.setState({
      config: config,
      optionLibs: options || optionLibs
      config: config
    })
  }
@@ -1377,7 +1356,6 @@
                config={config}
                pasteContent={this.state.pasteContent}
                sysRoles={this.props.sysRoles}
                optionLibs={this.state.optionLibs}
                updatesearch={this.updatesearch}
              />
              <div className="chart-view" style={{position: 'relative'}}>
src/templates/formtabconfig/index.jsx
@@ -38,7 +38,6 @@
class ComTableConfig extends Component {
  static propTpyes = {
    menu: PropTypes.any,
    optionLibs: PropTypes.any,
    btnTab: PropTypes.object,
    config: PropTypes.any,
    handleView: PropTypes.func
@@ -67,7 +66,6 @@
    profileVisible: false,   // 验证信息模态框
    editgroup: null,         // 当前编辑组
    groupVisible: false,     // 编辑组模态框
    optionLibs: null,        // 自定义下拉选项库
    activeKey: '0',          // 默认展开基本信息
    pasteVisible: false,     // 粘贴模态框
    sqlVerifing: false,      // sql验证
@@ -80,7 +78,7 @@
   * 2、设置操作类型、原始菜单信息(每次保存后重置)、已使用表及基本信息表单
   */
  UNSAFE_componentWillMount () {
    const { menu, btnTab, config, optionLibs } = this.props
    const { menu, btnTab, config } = this.props
    let _config = ''
    let columns = []
@@ -104,24 +102,6 @@
      if (menu && menu.LongParam && menu.LongParam.setting) {
        _config.setting.primaryKey = menu.LongParam.setting.primaryKey
      }
      _config.groups.forEach(group => {
        group.sublist.forEach(item => {
          if (
            (item.type === 'select' || item.type === 'multiselect' || item.type === 'link') &&
            item.resourceType === '0' &&
            item.options && item.options.length > 0
          ) {
            optionLibs.set(btnTab.uuid + item.uuid, {
              uuid: btnTab.uuid + item.uuid,
              label: item.label,
              parname: btnTab.label,
              type: 'Modal',
              options: item.options
            })
          }
        })
      })
    }
    if (!_config.tabgroups) {
@@ -153,7 +133,6 @@
      config: _config,
      activeKey: btnTab.activeKey || '0',
      openEdition: btnTab.open_edition || '',
      optionLibs: optionLibs,
      columns: columns,
      originMenu: JSON.parse(JSON.stringify(_config)),
      selectedTables: _config.tables,
@@ -355,7 +334,6 @@
    let _tabview = menu ? menu.LongParam.Template : ''
    let param = {
      editMenu: menu,
      optionLibs: this.state.optionLibs,
      editTab: null,
      tabConfig: null,
      editSubTab: null,
@@ -534,8 +512,7 @@
   * 3、添加或编辑列,保存时,如按钮位置设置为表格,则修改操作列显示状态
   */
  handleSubmit = () => {
    const { btnTab } = this.props
    const { config, modaltype, optionLibs, card } = this.state
    const { config, modaltype, card } = this.state
    if (modaltype === 'search') {
      this.modalFormRef.handleConfirm().then(res => {
@@ -548,19 +525,6 @@
            duration: 5
          })
          return
        }
        if ( // 更新下拉字典
          (res.type === 'select' || res.type === 'multiselect' || res.type === 'link') &&
          res.resourceType === '0' &&
          res.options && res.options.length > 0
        ) {
          optionLibs.set(btnTab.uuid + res.uuid, {
            uuid: btnTab.uuid + res.uuid,
            label: res.label,
            parname: btnTab.label,
            type: 'Modal',
            options: res.options
          })
        }
        let _groups = null
@@ -654,7 +618,6 @@
              this.setState({
                sqlVerifing: false,
                config: {..._config, groups: _groups},
                optionLibs: optionLibs,
                modaltype: ''
              })
            } else {
@@ -668,7 +631,6 @@
        } else {
          this.setState({
            config: {..._config, groups: _groups},
            optionLibs: optionLibs,
            modaltype: ''
          })
        }
@@ -1560,7 +1522,6 @@
          let param = {
            editMenu: menu,
            optionLibs: this.state.optionLibs,
            editTab: btn,
            tabConfig: null,
            editSubTab: null,
@@ -2005,7 +1966,6 @@
            card={this.state.card}
            formlist={this.state.formlist}
            inputSubmit={this.handleSubmit}
            optionLibs={this.state.optionLibs}
            wrappedComponentRef={(inst) => this.modalFormRef = inst}
          />
        </Modal>
src/templates/menuconfig/editthdmenu/index.jsx
@@ -76,7 +76,6 @@
    btnTabConfig: null,     // 打开新标签按钮配置
    handleMVisible: false,  // 添加或修改菜单模态框(角色权限分配等)
    sysMenu: false,         // 添加或编辑菜单(角色权限分配等)
    optionLibs: null,       // 自定义下拉选项库
    fstMenuId: null,        // 一级菜单Id
    fstMenuList: null       // 一级菜单列表
  }
@@ -211,7 +210,6 @@
              type: 'edit',
              editMenu: _menu,
              loading: false,
              optionLibs: new Map(), // 编辑时,初始化为空
              tabview: _menu.PageParam.Template
            }, () => {
              document.getElementById('root').style.overflowY = 'hidden'
@@ -220,8 +218,7 @@
            _menu.loadingFstMenuId = true
            this.setState({
              type: 'edit',
              editMenu: _menu,
              optionLibs: new Map()
              editMenu: _menu
            })
          }
        } else {
@@ -523,7 +520,6 @@
      this.setState({
        loading: false,
        tabview: template.type === 'CustomPage' ? '' : template.type,
        optionLibs: new Map(), // 新建时,初始化下拉选项库
        editMenu: {
          ...editMenu,
          type: template.type,
@@ -735,7 +731,6 @@
            type: 'edit',
            editMenu: _menu,
            loading: false,
            optionLibs: new Map(), // 编辑时,初始化为空
            tabview: _menu.PageParam.Template
          }, () => {
            document.getElementById('root').style.overflowY = 'hidden'
@@ -864,7 +859,6 @@
        {this.state.tabview === 'TreePage' ?
          <TreePageConfig
            menu={this.state.editMenu}
            optionLibs={this.state.optionLibs}
            reloadmenu={() => {this.props.reload()}}
            handleView={this.handleView}
          /> : null
@@ -872,7 +866,6 @@
        {this.state.tabview === 'CalendarPage' ?
          <CalendarPageConfig
            menu={this.state.editMenu}
            optionLibs={this.state.optionLibs}
            reloadmenu={() => {this.props.reload()}}
            handleView={this.handleView}
          /> : null
@@ -880,7 +873,6 @@
        {this.state.tabview === 'CommonTable' ?
          <ComTableConfig
            menu={this.state.editMenu}
            optionLibs={this.state.optionLibs}
            reloadmenu={() => {this.props.reload()}}
            handleView={this.handleView}
          /> : null
@@ -888,7 +880,6 @@
        {this.state.tabview === 'Modal' ?
          <ModalConfig
            menu={this.state.editMenu}
            optionLibs={this.state.optionLibs}
            editTab={this.state.editTab}
            tabConfig={this.state.tabConfig}
            editSubTab={this.state.editSubTab}
@@ -903,7 +894,6 @@
        {this.state.tabview === 'SubTable' ?
          <SubTable
            menu={this.state.editMenu}
            optionLibs={this.state.optionLibs}
            editTab={this.state.editTab}
            editSubTab={this.state.editSubTab}
            tabConfig={this.state.tabConfig}
@@ -916,7 +906,6 @@
        {this.state.tabview === 'FormTab' ?
          <FormTabConfig
            menu={this.state.editMenu}
            optionLibs={this.state.optionLibs}
            btnTab={this.state.btnTab}
            config={this.state.subConfig}
            handleView={this.handleView}
src/templates/modalconfig/dragelement/card.jsx
@@ -1,6 +1,6 @@
import React from 'react'
import { useDrag, useDrop } from 'react-dnd'
import { Icon, Select, DatePicker, Input, InputNumber, Button, Popover } from 'antd'
import { Icon, Select, DatePicker, Input, InputNumber, Button, Popover, Switch, Radio, Checkbox } from 'antd'
import moment from 'moment'
import './index.scss'
@@ -92,6 +92,22 @@
    formItem = (<Input style={{marginTop: '4px'}} defaultValue={card.linkfield} />)
  } else if (card.type === 'linkMain') {
    formItem = (<Input style={{marginTop: '4px'}} />)
  } else if (card.type === 'switch') {
    formItem = (<Switch style={{marginTop: '8px'}} checked={card.initval}/>)
  } else if (card.type === 'radio') {
    formItem = (<Radio.Group style={{marginTop: '8px'}} value={1}>
      <Radio value={1}>A</Radio>
      <Radio value={2}>B</Radio>
      <Radio value={3}>C</Radio>
      <Radio value={4}>D</Radio>
    </Radio.Group>)
  } else if (card.type === 'checkbox') {
    formItem = (<Checkbox.Group style={{marginTop: '8px'}} value={['A', 'C']}>
      <Checkbox value="A">A</Checkbox>
      <Checkbox value="B">B</Checkbox>
      <Checkbox value="C">C</Checkbox>
      <Checkbox value="D">D</Checkbox>
    </Checkbox.Group>)
  }
  return (
src/templates/modalconfig/index.jsx
@@ -33,7 +33,6 @@
class ComModalConfig extends Component {
  static propTpyes = {
    menu: PropTypes.any,
    optionLibs: PropTypes.any,
    editTab: PropTypes.any,
    editSubTab: PropTypes.any,
    tabConfig: PropTypes.any,
@@ -66,7 +65,6 @@
    originConfig: null,    // 原始菜单
    groupVisible: false,   // 全局配置模态框
    curgroup: null,        // 当前组,新建或编辑
    optionLibs: null,      // 自定义下拉选项库
    sources: null,         // 表单类型
    sqlVerifing: false,    // sql验证
    openEdition: ''        // 编辑版本标记,防止多人操作
@@ -80,7 +78,7 @@
   * 4、设置按钮基本信息
   */
  UNSAFE_componentWillMount () {
    const {menu, editAction, tabConfig, subTabConfig, subConfig, optionLibs} = this.props
    const {menu, editAction, tabConfig, subTabConfig, subConfig} = this.props
    let _config = ''
    let _tab = subTabConfig ? subTabConfig : tabConfig
@@ -95,42 +93,6 @@
    if (subConfig) {
      _config = subConfig
      if (_config.groups.length > 0) {
        _config.groups.forEach(group => {
          group.sublist.forEach(item => {
            if (
              (item.type === 'select' || item.type === 'multiselect' || item.type === 'link') &&
              item.resourceType === '0' &&
              item.options && item.options.length > 0
            ) {
              optionLibs.set(editAction.uuid + item.uuid, {
                uuid: editAction.uuid + item.uuid,
                label: item.label,
                parname: editAction.label,
                type: 'Modal',
                options: item.options
              })
            }
          })
        })
      } else {
        _config.fields.forEach(item => {
          if (
            (item.type === 'select' || item.type === 'multiselect' || item.type === 'link') &&
            item.resourceType === '0' &&
            item.options && item.options.length > 0
          ) {
            optionLibs.set(editAction.uuid + item.uuid, {
              uuid: editAction.uuid + item.uuid,
              label: item.label,
              parname: editAction.label,
              type: 'Modal',
              options: item.options
            })
          }
        })
      }
    } else {
      _config = JSON.parse(JSON.stringify(BaseConfig))
    }
@@ -156,7 +118,6 @@
      openEdition: editAction.open_edition || '',
      menu: _menu,
      source: _source,
      optionLibs: optionLibs,
      config: _config,
      selectedTables: _config.tables || [],
      originConfig: JSON.parse(JSON.stringify(_config)),
@@ -290,7 +251,6 @@
    
    let param = {
      editMenu: menu,
      optionLibs: this.state.optionLibs,
      editTab: editTab,
      tabConfig: tabConfig,
      editSubTab: editSubTab,
@@ -525,25 +485,10 @@
   * 3、通过loading刷新
   */
  handleSubmit = () => {
    const {editAction, optionLibs} = this.props
    const { card, modalType } = this.state
    this.formRef.handleConfirm().then(res => {
      let _config = JSON.parse(JSON.stringify(this.state.config))
      if ( // 更新下拉字典
        (res.type === 'select' || res.type === 'multiselect' || res.type === 'link') &&
        res.resourceType === '0' &&
        res.options && res.options.length > 0
      ) {
        optionLibs.set(editAction.uuid + res.uuid, {
          uuid: editAction.uuid + res.uuid,
          label: res.label,
          parname: editAction.label,
          type: 'Modal',
          options: res.options
        })
      }
      let fieldrepet = false // 字段重复
      let labelrepet = false // 提示文字重复
@@ -664,7 +609,6 @@
              config: _config,
              modalType: null,
              card: null,
              optionLibs: optionLibs,
              visible: false
            })
          } else {
@@ -680,7 +624,6 @@
          config: _config,
          modalType: null,
          card: null,
          optionLibs: optionLibs,
          visible: false
        })
      }
@@ -1358,7 +1301,7 @@
        <Modal
          title={this.state.modalType !== 'copy' ? this.state.dict['model.edit'] : this.state.dict['header.modal.form.copy']}
          visible={this.state.visible}
          width={700}
          width={800}
          onCancel={this.editModalCancel}
          onOk={this.handleSubmit}
          confirmLoading={this.state.sqlVerifing}
@@ -1369,7 +1312,6 @@
            card={this.state.card}
            formlist={this.state.formlist}
            inputSubmit={this.handleSubmit}
            optionLibs={this.state.optionLibs}
            wrappedComponentRef={(inst) => this.formRef = inst}
          />}
        </Modal>
src/templates/modalconfig/index.scss
@@ -219,6 +219,7 @@
                right: 0;
                bottom: 0;
                opacity: 0;
                z-index: 1;
              }
            }
            .ant-col-cuslabel {
src/templates/modalconfig/source.jsx
@@ -104,6 +104,30 @@
  },
  {
    type: 'form',
    label: '开关',
    subType: 'switch',
    url: ''
  },
  {
    type: 'form',
    label: '多选框',
    subType: 'checkbox',
    url: ''
  },
  {
    type: 'form',
    label: '单选框',
    subType: 'radio',
    url: ''
  },
  {
    type: 'form',
    label: '选项卡',
    subType: 'checkcard',
    url: ''
  },
  {
    type: 'form',
    label: CommonDict['header.form.fileupload'],
    subType: 'fileupload',
    url: ''
src/templates/sharecomponent/searchcomponent/index.jsx
@@ -21,7 +21,6 @@
    menu: PropTypes.object,          // 当前菜单信息
    config: PropTypes.object,        // 配置信息
    pasteContent: PropTypes.object,  // 粘贴配置信息
    optionLibs: PropTypes.any,       // 下拉字典
    sysRoles: PropTypes.array,       // 角色列表,黑名单
    updatesearch: PropTypes.func     // 更新
  }
@@ -128,7 +127,7 @@
   * 4、下拉菜单数据源语法验证
   */
  handleSubmit = () => {
    const { optionLibs, menu, config } = this.props
    const { config } = this.props
    let _searchlist = fromJS(this.state.searchlist).toJS()
    this.searchFormRef.handleConfirm().then(res => {
@@ -189,16 +188,6 @@
        return
      }
      if ( res.options && res.options.length > 0 ) { // 下拉菜单可选集合
        optionLibs.set(menu.MenuID + res.uuid, {
          uuid: menu.MenuID + res.uuid,
          label: res.label,
          parname: menu.MenuName,
          type: 'search',
          options: res.options
        })
      }
      if ((res.type === 'select' || res.type === 'multiselect' || res.type === 'link') && res.resourceType === '1' && /\s/.test(res.dataSource)) {
        this.setState({
          sqlVerifing: true
@@ -226,7 +215,7 @@
              searchlist: _searchlist,
              visible: false
            }, ()=> {
              this.props.updatesearch({...config, search: _searchlist}, optionLibs)
              this.props.updatesearch({...config, search: _searchlist})
            })
          } else {
            this.setState({sqlVerifing: false})
@@ -241,7 +230,7 @@
          searchlist: _searchlist,
          visible: false
        }, ()=> { 
          this.props.updatesearch({...config, search: _searchlist}, optionLibs)
          this.props.updatesearch({...config, search: _searchlist})
        })
      }
    })
@@ -316,7 +305,6 @@
            card={this.state.card}
            formlist={this.state.formlist}
            inputSubmit={this.handleSubmit}
            optionLibs={this.props.optionLibs}
            wrappedComponentRef={(inst) => this.searchFormRef = inst}
          />
        </Modal>
src/templates/sharecomponent/searchcomponent/searchform/index.jsx
@@ -84,7 +84,6 @@
  static propTpyes = {
    dict: PropTypes.object,     // 字典项
    formlist: PropTypes.any,    // 表单
    optionLibs: PropTypes.any,  // 自定义下拉集
    card: PropTypes.object,     // 搜索条件信息
    inputSubmit: PropTypes.any  // 回车提交事件
  }
@@ -102,7 +101,7 @@
   * 2、下拉选择,根据数据源类型显示相关配置
   */
  UNSAFE_componentWillMount () {
    const { formlist, optionLibs, dict } = this.props
    const { formlist, dict } = this.props
    let type = formlist.filter(cell => cell.key === 'type')[0].initVal
    let _items = formlist.filter(cell => cell.key === 'items')[0].initVal
@@ -110,7 +109,7 @@
    let _options = ['label', 'field', 'initval', 'type', 'match', 'ratio', 'blacklist', 'required', 'Hide']                // 默认显示项
    if ((type === 'multiselect' || type === 'select' || type === 'link') && resourceType === '0') {        // 下拉选择类型、选项为自定义资源
      _options = [..._options, 'resourceType', 'options', 'display', 'quick']
      _options = [..._options, 'resourceType', 'options', 'display']
    } else if ((type === 'multiselect' || type === 'select' || type === 'link') && resourceType === '1') { // 下拉选择类型、选项为后台数据源中获取
      _options = [..._options, 'resourceType', 'dataSource', 'valueField', 'valueText', 'orderBy', 'orderType', 'display', 'database']
    } else if (type === 'group') {
@@ -151,13 +150,6 @@
          } else if (type === 'dateweek' || type === 'daterange') {
            form.options = matchReg.daterange
          }
        } else if (form.key === 'quick') {
          form.options = [...optionLibs.values()].map(cell => {
            return {
              value: cell.uuid,
              text: cell.label + '(' + cell.parname + ')'
            }
          })
        } else if (form.key === 'field' && type === 'text') {
          form.tooltip = this.state.textTooltip
        } else if (form.key === 'field' && type === 'group') {
@@ -193,7 +185,7 @@
      let _options = ['label', 'field', 'initval', 'type', 'match', 'ratio', 'blacklist', 'required', 'Hide']
      if ((value === 'multiselect' || value === 'select' || value === 'link') && resourceType === '0') {        // 下拉选择类型、选项为自定义资源
        _options = [..._options, 'resourceType', 'options', 'display', 'quick']
        _options = [..._options, 'resourceType', 'options', 'display']
      } else if ((value === 'multiselect' || value === 'select' || value === 'link') && resourceType === '1') { // 下拉选择类型、选项为后台数据源中获取
        _options = [..._options, 'resourceType', 'dataSource', 'valueField', 'valueText', 'orderBy', 'orderType', 'display', 'database']
      } else if (value === 'group') {
@@ -260,18 +252,6 @@
          this.props.form.setFieldsValue({match: matchs[0].value})
        }
      })
    } else if (key === 'quick') {
      let _option = this.props.optionLibs.get(value)
      this.setState({
        formlist: this.state.formlist.map(form => {
          if (form.key === 'options') {
            form.initVal = _option.options
          }
          return form
        })
      })
    }
  }
@@ -286,7 +266,7 @@
      let _options = ['label', 'field', 'initval', 'type', 'match', 'resourceType', 'display', 'ratio', 'blacklist', 'required', 'Hide']
      if (value === '0') {
        _options = [..._options, 'options', 'quick']
        _options = [..._options, 'options']
      } else if (value === '1') {
        _options = [..._options, 'dataSource', 'valueField', 'valueText', 'orderBy', 'orderType', 'database']
      }
src/templates/sharecomponent/settingcomponent/settingform/datasource/index.jsx
@@ -412,6 +412,17 @@
                </Radio.Group>)}
              </Form.Item>
            </Col> : null}
            <Col span={12}>
              <Form.Item label="边框">
                {getFieldDecorator('bordered', {
                  initialValue: setting.bordered || 'true'
                })(
                <Radio.Group>
                  <Radio value="true">有</Radio>
                  <Radio value="false">无</Radio>
                </Radio.Group>)}
              </Form.Item>
            </Col>
          </Row>
        </Form>
      </div>
src/templates/subtableconfig/index.jsx
@@ -37,7 +37,6 @@
class SubTableConfig extends Component {
  static propTpyes = {
    menu: PropTypes.any,
    optionLibs: PropTypes.any,
    editTab: PropTypes.any,
    tabConfig: PropTypes.any,
    editSubTab: PropTypes.any,
@@ -61,7 +60,6 @@
    delActions: [],          // 删除按钮列表
    copyActions: [],         // 复制按钮组
    tabviews: [],            // 所有标签页
    optionLibs: null,        // 自定义下拉选项库
    thawButtons: [],         // 已选择要解冻的按钮
    activeKey: '0',          // 默认展开基本信息
    chartview: null,         // 当前视图
@@ -75,7 +73,7 @@
   * 2、设置操作类型、原始菜单信息(每次保存后重置)、已使用表及基本信息表单
   */
  UNSAFE_componentWillMount () {
    const { config, editTab, editSubTab, optionLibs } = this.props
    const { config, editTab, editSubTab } = this.props
    let _config = null
@@ -86,22 +84,6 @@
      _config.isAdd = true
    } else {
      _config = fromJS(config).toJS()
      _config.search.forEach(item => {
        if (
          (item.type === 'select' || item.type === 'multiselect' || item.type === 'link') &&
          item.resourceType === '0' &&
          item.options && item.options.length > 0
        ) {
          optionLibs.set(_config.uuid + item.uuid, {
            uuid: _config.uuid + item.uuid,
            label: item.label,
            parname: _config.tabName,
            type: 'search',
            options: item.options
          })
        }
      })
    }
    
    let _oriActions = []
@@ -131,7 +113,6 @@
      openEdition: editSubTab ? (editSubTab.open_edition || '') : (editTab.open_edition || ''),
      chartview: _config.charts[0].uuid,
      originActions: _oriActions,
      optionLibs: optionLibs,
      config: _config,
      activeKey: _activeKey || '0',
      originConfig: fromJS(_config).toJS(),
@@ -226,7 +207,6 @@
    let param = {
      editMenu: menu,
      optionLibs: this.state.optionLibs,
      editTab: editSubTab ? editTab : null,
      tabConfig: null,
      editSubTab: null,
@@ -797,7 +777,6 @@
        let param = {
          editMenu: menu,
          optionLibs: this.state.optionLibs,
          editTab: editTab,
          tabConfig: editSubTab ? tabConfig : originConfig,
          editSubTab: _subtab,
@@ -956,12 +935,10 @@
  /**
   * @description 更新搜索条件配置信息
   */
  updatesearch = (config, options) => {
    const { optionLibs } = this.state
  updatesearch = (config) => {
    this.setState({
      config: config,
      optionLibs: options || optionLibs
      config: config
    })
  }
@@ -1130,7 +1107,6 @@
                config={config}
                pasteContent={this.state.pasteContent}
                sysRoles={this.props.sysRoles}
                optionLibs={this.state.optionLibs}
                updatesearch={this.updatesearch}
              />
              <div className="chart-view" style={{position: 'relative'}}>
src/templates/treepageconfig/index.jsx
@@ -29,7 +29,6 @@
class ComTableConfig extends Component {
  static propTpyes = {
    menu: PropTypes.any,
    optionLibs: PropTypes.any,
    reloadmenu: PropTypes.func,
    handleView: PropTypes.func
  }
@@ -46,7 +45,6 @@
    originMenu: null,        // 原始菜单
    delTabs: [],             // 删除标签列表
    tabviews: [],            // 所有标签页
    optionLibs: null,        // 自定义下拉选项库
    activeKey: '0',          // 默认展开基本信息
    pasteContent: null,      // 粘贴配置信息
    openEdition: ''          // 编辑版本标记,防止多人操作
@@ -58,7 +56,7 @@
   * 2、设置操作类型、原始菜单信息(每次保存后重置)、已使用表及基本信息表单
   */
  UNSAFE_componentWillMount () {
    const { menu, optionLibs } = this.props
    const { menu } = this.props
    let _LongParam = menu.LongParam
    let _config = ''
@@ -105,7 +103,6 @@
      config: _config,
      openEdition: menu.open_edition || '',
      activeKey: menu.activeKey || '0',
      optionLibs: optionLibs,
      originMenu: fromJS(_config).toJS()
    })
  }
@@ -554,7 +551,7 @@
   */
  setSubConfig = (item) => {
    const { menu } = this.props
    const { config, originMenu, optionLibs, activeKey, openEdition } = this.state
    const { config, originMenu, activeKey, openEdition } = this.state
    if (config.isAdd) { // menuID不存在时,为新建菜单,提示菜单尚未保存
      notification.warning({
@@ -600,7 +597,6 @@
      _Menu.open_edition = openEdition  // 更新版本号
      let param = {
        optionLibs: optionLibs,
        editMenu: _Menu,
        editTab: item,
        tabConfig: null,
src/templates/zshare/formconfig.jsx
@@ -534,14 +534,6 @@
      required: false
    },
    {
      type: 'select',
      key: 'quick',
      label: Formdict['header.form.quickadd'],
      initVal: '',
      required: false,
      options: []
    },
    {
      type: 'radio',
      key: 'required',
      label: Formdict['model.required'],
@@ -1822,6 +1814,18 @@
        value: 'link',
        text: Formdict['model.form.link']
      }, {
        value: 'switch',
        text: '开关'
      }, {
        value: 'checkbox',
        text: '多选框'
      }, {
        value: 'radio',
        text: '单选框'
      }, {
        value: 'checkcard',
        text: '选项卡'
      }, {
        value: 'fileupload',
        text: Formdict['header.form.fileupload']
      }, {
@@ -1849,8 +1853,23 @@
      type: 'text',
      key: 'initval',
      label: Formdict['header.form.initval'],
      tooltip: '下拉多选与多选框,添加多个初始值请使用“,”号分隔。',
      initVal: card.initval || '',
      required: false
    },
    {
      type: 'text',
      key: 'openVal',
      label: '开启值',
      initVal: card.openVal || '',
      required: true
    },
    {
      type: 'text',
      key: 'closeVal',
      label: '关闭值',
      initVal: card.closeVal || '',
      required: true
    },
    {
      type: 'radio',
@@ -1864,6 +1883,20 @@
      }, {
        value: '1',
        text: Formdict['header.form.datasource']
      }]
    },
    {
      type: 'radio',
      key: 'display',
      label: '显示',
      initVal: card.display || 'text',
      required: true,
      options: [{
        value: 'text',
        text: '文本'
      }, {
        value: 'picture',
        text: '图片'
      }]
    },
    {
@@ -2017,14 +2050,6 @@
    },
    {
      type: 'select',
      key: 'quick',
      label: Formdict['header.form.quickadd'],
      initVal: '',
      required: false,
      options: []
    },
    {
      type: 'select',
      key: 'fileType',
      label: '显示方式',
      initVal: card.fileType || 'text',
@@ -2128,6 +2153,20 @@
    },
    {
      type: 'radio',
      key: 'entireLine',
      label: '占据整行',
      initVal: card.entireLine || 'false',
      required: false,
      options: [{
        value: 'true',
        text: '是'
      }, {
        value: 'false',
        text: '否'
      }]
    },
    {
      type: 'radio',
      key: 'encryption',
      label: '加密传输',
      initVal: card.encryption || 'false',
src/templates/zshare/modalform/index.jsx
@@ -1,5 +1,6 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import { fromJS } from 'immutable'
import { Form, Row, Col, Input, Select, Icon, Radio, notification, InputNumber, Tooltip } from 'antd'
import { formRule } from '@/utils/option.js'
import { dateOptions } from '@/utils/option.js'
@@ -9,25 +10,28 @@
import './index.scss'
const modalTypeOptions = {
  text: ['label', 'field', 'initval', 'type', 'readonly', 'required', 'hidden', 'readin', 'blacklist', 'fieldlength', 'regular', 'interception', 'writein'],
  number: ['label', 'field', 'initval', 'type', 'readonly', 'hidden', 'decimal', 'min', 'max', 'readin', 'blacklist', 'writein'],
  select: ['label', 'field', 'initval', 'type', 'readonly', 'required', 'hidden', 'readin', 'blacklist', 'resourceType', 'setAll', 'linkSubField', 'writein'],
  multiselect: ['label', 'field', 'initval', 'type', 'readonly', 'required', 'hidden', 'readin', 'blacklist', 'resourceType', 'fieldlength', 'writein'],
  link: ['label', 'field', 'initval', 'type', 'readonly', 'required', 'hidden', 'readin', 'blacklist', 'resourceType', 'setAll', 'linkField', 'writein'],
  fileupload: ['label', 'field', 'type', 'readonly', 'required', 'readin', 'fieldlength', 'blacklist', 'maxfile', 'fileType', 'writein'],
  date: ['label', 'field', 'initval', 'type', 'readonly', 'required', 'hidden', 'readin', 'blacklist', 'writein'],
  datemonth: ['label', 'field', 'initval', 'type', 'readonly', 'required', 'hidden', 'readin', 'blacklist', 'writein'],
  datetime: ['label', 'field', 'initval', 'type', 'readonly', 'required', 'hidden', 'readin', 'blacklist', 'writein'],
  textarea: ['label', 'field', 'initval', 'type', 'readonly', 'required', 'hidden', 'readin', 'blacklist', 'fieldlength', 'maxRows', 'encryption', 'interception', 'writein'],
  color: ['label', 'field', 'type', 'blacklist', 'readonly', 'required', 'hidden', 'readin', 'writein'],
  funcvar: ['label', 'field', 'type', 'blacklist', 'hidden', 'writein'],
  linkMain: ['label', 'field', 'type', 'readonly', 'required', 'hidden', 'fieldlength', 'blacklist', 'writein']
  text: ['initval', 'readonly', 'required', 'hidden', 'readin', 'fieldlength', 'regular', 'interception', 'entireLine'],
  number: ['initval', 'readonly', 'hidden', 'decimal', 'min', 'max', 'readin', 'entireLine'],
  select: ['initval', 'readonly', 'required', 'hidden', 'readin', 'resourceType', 'setAll', 'linkSubField', 'entireLine'],
  checkbox: ['initval', 'readonly', 'required', 'hidden', 'readin', 'resourceType', 'linkSubField', 'entireLine'],
  radio: ['initval', 'readonly', 'required', 'hidden', 'readin', 'resourceType', 'linkSubField', 'entireLine'],
  checkcard: ['initval', 'readonly', 'required', 'hidden', 'readin', 'resourceType', 'linkSubField', 'display'],
  multiselect: ['initval', 'readonly', 'required', 'hidden', 'readin', 'resourceType', 'fieldlength', 'entireLine'],
  link: ['initval', 'readonly', 'required', 'hidden', 'readin', 'resourceType', 'setAll', 'linkField', 'entireLine'],
  fileupload: ['readonly', 'required', 'readin', 'fieldlength', 'maxfile', 'fileType', 'entireLine'],
  switch: ['initval', 'openVal', 'closeVal', 'readonly', 'required', 'hidden', 'readin', 'entireLine'],
  date: ['initval', 'readonly', 'required', 'hidden', 'readin', 'entireLine'],
  datemonth: ['initval', 'readonly', 'required', 'hidden', 'readin', 'entireLine'],
  datetime: ['initval', 'readonly', 'required', 'hidden', 'readin', 'entireLine'],
  textarea: ['initval', 'readonly', 'required', 'hidden', 'readin', 'fieldlength', 'maxRows', 'encryption', 'interception'],
  color: ['readonly', 'required', 'hidden', 'readin', 'entireLine'],
  funcvar: ['hidden'],
  linkMain: ['readonly', 'required', 'hidden', 'fieldlength', 'entireLine']
}
class MainSearch extends Component {
  static propTpyes = {
    dict: PropTypes.object,    // 字典项
    optionLibs: PropTypes.any, // 自定义下拉集
    formlist: PropTypes.any,
    card: PropTypes.object,
    inputSubmit: PropTypes.any
@@ -42,8 +46,7 @@
  }
  UNSAFE_componentWillMount () {
    const { optionLibs } = this.props
    let formlist = JSON.parse(JSON.stringify(this.props.formlist))
    let formlist = fromJS(this.props.formlist).toJS()
    let type = ''
    let resourceType = ''
@@ -70,21 +73,7 @@
      }
    })
    
    let _options = JSON.parse(JSON.stringify(modalTypeOptions[type]))
    if ((type === 'multiselect' || type === 'select' || type === 'link') && resourceType === '0') { // 选择类型、自定义资源
      _options = [..._options, 'options', 'quick']
    } else if ((type === 'multiselect' || type === 'select' || type === 'link') && resourceType === '1') { // 选择类型、数据源
      _options = [..._options, 'dataSource', 'valueField', 'valueText', 'orderBy', 'orderType', 'database']
    }
    if (type !== 'funcvar' && type !== 'linkMain') {
      if (supField) {
        _options.push('supField', 'supvalue')
      } else {
        _options.push('supField')
      }
    }
    let _options = this.getOptions(type, resourceType, supField)
    this.setState({
      openType: type,
@@ -95,17 +84,17 @@
        if (dateOptions.hasOwnProperty(type) && form.key === 'initval') {
          form.options = dateOptions[type]
          form.type = 'select'
        } else if (type === 'switch' && form.key === 'initval') {
          form.initVal = !!form.initVal
          form.options = [
            {value: true, text: '开'},
            {value: false, text: '关'}
          ]
          form.type = 'radio'
        } else if (type === 'number' && form.key === 'initval') {
          form.type = 'number'
          form.initVal = form.initVal || 0
          form.required = true
        } else if (form.key === 'quick') {
          form.options = [...optionLibs.values()].map(cell => {
            return {
              value: cell.uuid,
              text: cell.label + '(' + cell.parname + ')'
            }
          })
        }
        form.show = _options.includes(form.key)
@@ -127,24 +116,31 @@
    }
  }
  openTypeChange = (key, value) => {
    if (key === 'type') {
      let _options = JSON.parse(JSON.stringify(modalTypeOptions[value]))
  getOptions = (type, resourceType, supField) => {
    let _options = ['label', 'field', 'type', 'blacklist', 'writein', ...fromJS(modalTypeOptions[type]).toJS()]
      if ((value === 'multiselect' || value === 'select' || value === 'link') && this.state.resourceType === '0') { // 选择类型、自定义资源
        _options = [..._options, 'options', 'quick']
      } else if ((value === 'multiselect' || value === 'select' || value === 'link') && this.state.resourceType === '1') { // 选择类型、数据源
    if (['multiselect', 'select', 'link', 'radio', 'checkbox', 'checkcard'].includes(type)) {
      if (resourceType === '0') {        // 自定义资源
        _options = [..._options, 'options']
      } else if (resourceType === '1') { // 数据源
        _options = [..._options, 'dataSource', 'valueField', 'valueText', 'orderBy', 'orderType', 'database']
      }
    }
      if (value !== 'funcvar' && value !== 'linkMain') {
        if (this.state.supField) {
    if (type !== 'funcvar' && type !== 'linkMain') {
      if (supField) {
          _options.push('supField', 'supvalue')
        } else {
          _options.push('supField')
        }
      }
    return _options
  }
  openTypeChange = (key, value) => {
    if (key === 'type') {
      let _options = this.getOptions(value, this.state.resourceType, this.state.supField)
      let fieldValue = {}
      
      this.setState({
@@ -157,6 +153,13 @@
            if (dateOptions.hasOwnProperty(value)) {
              form.options = dateOptions[value]
              form.type = 'select'
            } else if (value === 'switch') {
              form.initVal = false
              form.options = [
                {value: true, text: '开'},
                {value: false, text: '关'}
              ]
              form.type = 'radio'
            } else if (value === 'number') {
              form.type = 'number'
              form.required = true
@@ -170,7 +173,7 @@
            }
          } else if (form.key === 'fieldlength') {
            form.initVal = 50
            if (value === 'textarea' || value === 'fileupload' || value === 'multiselect') {
            if (value === 'textarea' || value === 'fileupload' || value === 'multiselect' || value === 'checkbox') {
              form.initVal = 512
            }
@@ -194,18 +197,6 @@
        })
      }, () => {
        this.props.form.setFieldsValue(fieldValue)
      })
    } else if (key === 'quick') {
      let option = this.props.optionLibs.get(value)
      this.setState({
        formlist: this.state.formlist.map(form => {
          if (form.key === 'options') {
            form.initVal = option.options
          }
          return form
        })
      })
    } else if (key === 'supField') {
      this.setState({
@@ -249,21 +240,7 @@
    const { openType } = this.state
    let value = e.target.value
    if (key === 'resourceType') {
      let _options = JSON.parse(JSON.stringify(modalTypeOptions[openType]))
      if (value === '0') {
        _options = [..._options, 'options', 'quick']
      } else if (value === '1') {
        _options = [..._options, 'dataSource', 'valueField', 'valueText', 'orderBy', 'orderType', 'database']
      }
      if (openType !== 'funcvar' && openType !== 'linkMain') {
        if (this.state.supField) {
          _options.push('supField', 'supvalue')
        } else {
          _options.push('supField')
        }
      }
      let _options = this.getOptions(openType, value, this.state.supField)
      this.setState({
        resourceType: value,
@@ -500,7 +477,12 @@
      } else if (item.type === 'options') {
        fields.push(
          <Col span={20} offset={4} key={index}>
            <EditTable data={item.initVal} dict={this.props.dict} type={this.state.openType} linkSubFields={this.state.linkSubFields} ref="editTable"/>
            <Form.Item className="text-area">
              {getFieldDecorator(item.key, {
                initialValue: item.initVal
              })(<EditTable dict={this.props.dict} type={this.state.openType} linkSubFields={this.state.linkSubFields}/>)}
            </Form.Item>
            {/* <EditTable data={item.initVal} dict={this.props.dict} type={this.state.openType} linkSubFields={this.state.linkSubFields} ref="editTable"/> */}
          </Col>
        )
      }
@@ -514,38 +496,43 @@
    return new Promise((resolve, reject) => {
      this.props.form.validateFieldsAndScroll((err, values) => {
        if (!err) {
          let isvalid = true
          values.uuid = this.props.card.uuid
          // 下拉菜单或联动菜单
          if ((values.type === 'multiselect' || values.type === 'select' || values.type === 'link') && values.resourceType === '0') {
            values.options = this.refs.editTable.state.dataSource
          if (['multiselect', 'select', 'link', 'radio', 'checkbox'].includes(values.type)) {
            if (values.resourceType === '0') {
              values.options = values.options || []
            values.dataSource = ''
            let emptys = []
            if (values.type === 'multiselect' || values.type === 'select') {
              emptys = values.options.filter(op => !((op.Value || op.Value === 0) && (op.Text || op.Text === 0)))
            } else {
              emptys = values.options.filter(op => !((op.Value || op.Value === 0) && (op.Text || op.Text === 0) && (op.ParentID || op.ParentID === 0)))
              let empty = false
              values.options.forEach(op => {
                if (!((op.Value || op.Value === 0) && (op.Text || op.Text === 0))) {
                  empty = true
                } else if (values.type === 'link' && !(op.ParentID || op.ParentID === 0)) {
                  empty = true
            }
            if (emptys.length > 0) {
              isvalid = false
              })
              if (empty) {
              notification.warning({
                top: 92,
                message: this.props.dict['model.form.selectItem.error'],
                duration: 5
              })
                return
            }
          } else if ((values.type === 'multiselect' || values.type === 'select' || values.type === 'link') && values.resourceType === '1') {
            } else {
            values.options = []
            }
          } else if (values.type === 'funcvar') { // 函数变量为只读元素
            values.readonly = 'true'
          } else if (values.type === 'number' && (values.min || values.min === 0) && (values.max || values.max === 0)) { // 数值型验证最小最大值
            if (values.min > values.max) {
              isvalid = false
              notification.warning({
                top: 92,
                message: '最小值不可大于最大值!',
                duration: 5
              })
              return
            }
          } else if (values.type === 'linkMain') {
            values.initval = ''
@@ -568,9 +555,7 @@
            return
          }
          if (isvalid) {
            resolve(values)
          }
        } else {
          reject(err)
        }
src/templates/zshare/modalform/modaleditable/index.jsx
@@ -1,4 +1,5 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import { is, fromJS } from 'immutable'
import { Table, Input, Popconfirm, Form, Icon, Radio } from 'antd'
import { formRule } from '@/utils/option.js'
@@ -107,24 +108,44 @@
}
class EditTable extends Component {
  constructor(props) {
    super(props)
  static propTpyes = {
    dict: PropTypes.object,         // 字典项
    type: PropTypes.string,         // 表单类型
    linkSubFields: PropTypes.array, // 关联字段
    onChange: PropTypes.func        // 数据变化
  }
  state = {
    columns: [],
    dataSource: [],
    count: 0,
    type: null,
    linkSubFields: []
  }
  UNSAFE_componentWillMount () {
    const { linkSubFields, type, dict } = this.props
    let data = this.props['data-__meta'].initialValue
    if (!data) {
      data = []
    }
    let _width = '40%'
    let fields = []
    let dataItem = props.data ? props.data[0] : ''
    let dataItem = data[0] || ''
    if (props.type === 'link') {
    if (type === 'link') {
      _width = '27%'
    } else if (props.type === 'select') {
      _width = Math.floor(80 / (props.linkSubFields.length + 2)) + '%'
      fields = props.linkSubFields.map(field => {
    } else if (type === 'select') {
      _width = Math.floor(80 / (linkSubFields.length + 2)) + '%'
      fields = linkSubFields.map(cell => {
        return {
          title: field.label,
          dataIndex: field.field,
          title: cell.label,
          dataIndex: cell.field,
          width: _width,
          editable: true,
          datatype: dataItem && typeof(dataItem[field.field]) === 'number' ? 'number' : 'string'
          datatype: dataItem && typeof(dataItem[cell.field]) === 'number' ? 'number' : 'string'
        }
      })
    }
@@ -154,21 +175,21 @@
        render: (text, record) =>
          this.state.dataSource.length >= 1 ? (
            <div>
              <span className="operation-btn" title={props.dict['header.form.up']} onClick={() => this.handleUpDown(record, 'up')} style={{color: '#1890ff'}}><Icon type="arrow-up" /></span>
              <span className="operation-btn" title={props.dict['header.form.down']} onClick={() => this.handleUpDown(record, 'down')} style={{color: '#ff4d4f'}}><Icon type="arrow-down" /></span>
              <span className="operation-btn" title={dict['header.form.up']} onClick={() => this.handleUpDown(record, 'up')} style={{color: '#1890ff'}}><Icon type="arrow-up" /></span>
              <span className="operation-btn" title={dict['header.form.down']} onClick={() => this.handleUpDown(record, 'down')} style={{color: '#ff4d4f'}}><Icon type="arrow-down" /></span>
              <Popconfirm
                overlayClassName="popover-confirm"
                title={props.dict['model.query.delete']}
                title={dict['model.query.delete']}
                onConfirm={() => this.handleDelete(record.key)
              }>
                <span style={{color: '#1890ff', cursor: 'pointer'}}><Icon type="delete" /></span>
                <span style={{color: '#ff4d4f', cursor: 'pointer'}}><Icon type="delete" /></span>
              </Popconfirm>
            </div>
          ) : null,
      }
    ]
    if (props.type === 'link') {
    if (type === 'link') {
      columns.unshift({
        title: 'ParentID',
        dataIndex: 'ParentID',
@@ -178,18 +199,18 @@
      })
    }
    this.state = {
    this.setState({
      columns: columns.map(col => {
        if (col.dataIndex !== 'operation') {
          col = {...col, ...this.getColumnSearchProps(col)}
        }
        return col
      }),
      dataSource: props.data,
      count: props.data.length,
      type: props.type,
      linkSubFields: props.linkSubFields
    }
      dataSource: data,
      count: data.length,
      type: type,
      linkSubFields: linkSubFields
    })
  }
  getColumnSearchProps = column => ({
@@ -197,10 +218,10 @@
      <div style={{ padding: 8 }}>
        <Radio.Group onChange={(e) => this.changeDatatype(column, e)} value={column.datatype}>
          <Radio style={{display: 'block', height: '30px', lineHeight: '30px'}} value="string">
            String
            字符串
          </Radio>
          <Radio style={{display: 'block', height: '30px', lineHeight: '30px'}} value="number">
            Number
            数字
          </Radio>
        </Radio.Group>
      </div>
@@ -213,9 +234,7 @@
  changeDatatype = (column, e) => {
    const { columns, dataSource } = this.state
    let value = e.target.value
    this.setState({
      dataSource: dataSource.map(item => {
    let _data = dataSource.map(item => {
        let val = item[column.dataIndex]
        if (value === 'number') {
          try {
@@ -233,7 +252,10 @@
        item[column.dataIndex] = val
        return item
      }),
    })
    this.setState({
      dataSource: _data,
      columns: columns.map(col => {
        if (col.dataIndex === column.dataIndex) {
          col.datatype = value
@@ -245,6 +267,8 @@
        return col
      })
    }, () => {
      this.props.onChange(_data)
    })
  }
@@ -271,12 +295,18 @@
    this.setState({
      dataSource: _data
    }, () => {
      this.props.onChange(_data)
    })
  }
  handleDelete = key => {
    const dataSource = [...this.state.dataSource]
    this.setState({ dataSource: dataSource.filter(item => item.key !== key) })
    const { dataSource } = this.state
    let _data = dataSource.filter(item => item.key !== key)
    this.setState({ dataSource: _data }, () => {
      this.props.onChange(_data)
    })
  }
  handleAdd = () => {
@@ -289,9 +319,14 @@
    if (type === 'link') {
      newData.ParentID = `${count}`
    }
    let _data = [...dataSource, newData]
    this.setState({
      dataSource: [...dataSource, newData],
      dataSource: _data,
      count: count + 1
    }, () => {
      this.props.onChange(_data)
    })
  }
@@ -303,7 +338,9 @@
      ...item,
      ...row
    })
    this.setState({ dataSource: newData })
    this.setState({ dataSource: newData }, () => {
      this.props.onChange(newData)
    })
  }
  resetColumn = (type, linkSubFields) => {
@@ -392,28 +429,14 @@
      }),
      dataSource: dataSource,
      type: type
    }, () => {
      this.props.onChange(dataSource)
    })
  }
  UNSAFE_componentWillReceiveProps (nextProps) {
    if (!is(fromJS(this.props.linkSubFields), fromJS(nextProps.linkSubFields)) || this.props.type !== nextProps.type) {
      this.resetColumn(nextProps.type, nextProps.linkSubFields)
    } else if (!is(fromJS(this.props.data), fromJS(nextProps.data))) {
      let _data = []
      nextProps.data.forEach(item => {
        let _item = {key: Utils.getuuid()}
        this.state.columns.forEach(col => {
          _item[col.dataIndex] = item[col.dataIndex] || ''
          if (col.dataIndex !== 'ParentID' && !_item[col.dataIndex]) {
            _item[col.dataIndex] = item.Text
          }
        })
        _data.push(_item)
      })
      this.setState({
        dataSource: _data,
        count: nextProps.data.length
      })
    }
  }