king
2020-04-09 2ff464f30d94235b3ad04475593b75a74a354de9
src/templates/subtableconfig/index.jsx
@@ -6,21 +6,32 @@
import HTML5Backend from 'react-dnd-html5-backend'
import { Button, Card, Modal, Collapse, notification, Spin, Select, List, Icon, Empty, Switch, Tooltip } from 'antd'
import moment from 'moment'
import Api from '@/api'
import ActionForm from './actionform'
import SettingForm from './settingform'
import SearchForm from '@/templates/tableshare/searchform'
import ColumnForm from '@/templates/tableshare/columnform'
import DragElement from '@/templates/tableshare/dragelement'
import ColspanForm from '@/templates/tableshare/colspanform'
import GridBtnForm from '@/templates/tableshare/gridbtnform'
import EditCard from '@/templates/tableshare/editcard'
import VerifyCard from '@/templates/tableshare/verifycard'
import MenuForm from '@/templates/tableshare/menuform'
import SourceElement from '@/templates/tableshare/dragelement/source'
import options from '@/store/options.js'
import zhCN from '@/locales/zh-CN/comtable.js'
import enUS from '@/locales/en-US/comtable.js'
import Utils from '@/utils/utils.js'
import { getSearchForm, getActionForm, getColumnForm } from '@/templates/zshare/formconfig'
import { queryTableSql } from '@/utils/option.js'
import ActionForm from './actionform'
import SettingForm from './settingform'
import SearchForm from '@/templates/zshare/searchform'
import ColumnForm from '@/templates/zshare/columnform'
import DragElement from '@/templates/zshare/dragelement'
import PasteForm from '@/templates/zshare/pasteform'
import ColspanForm from '@/templates/zshare/colspanform'
import GridBtnForm from '@/templates/zshare/gridbtnform'
import EditCard from '@/templates/zshare/editcard'
import VerifyCard from '@/templates/zshare/verifycard'
import VerifyCardExcelIn from '@/templates/zshare/verifycardexcelin'
import VerifyCardExcelOut from '@/templates/zshare/verifycardexcelout'
import MenuForm from '@/templates/zshare/menuform'
import TransferForm from '@/components/transferform'
import SourceElement from '@/templates/zshare/dragelement/source'
import CreateFunc from '@/templates/zshare/createfunc'
import CreateInterface from '@/templates/zshare/createinterface'
import Source from './source'
import './index.scss'
@@ -31,11 +42,15 @@
class SubTableConfig extends Component {
  static propTpyes = {
    config: PropTypes.object,
    menu: PropTypes.any,
    handleConfig: PropTypes.func,
    handleSubConfig: PropTypes.func,
    supMenuList: PropTypes.array
    optionLibs: PropTypes.any,
    editTab: PropTypes.any,
    tabConfig: PropTypes.any,
    editSubTab: PropTypes.any,
    btnTab: PropTypes.any,
    btnTabConfig: PropTypes.any,
    config: PropTypes.any,
    handleView: PropTypes.func
  }
  state = {
@@ -50,10 +65,8 @@
    menuformlist: null,      // 基本信息表单字段
    formlist: null,          // 搜索条件、按钮、显示列表单字段
    formtemp: '',            // 表单类型,显示列、按钮、搜索条件
    modaltype: '',           // 模态框类型,控制模态框显示
    card: null,              // 编辑元素
    searchloading: false,    // 搜索条件加载中
    actionloading: false,    // 按钮加载中
    columnsloading: false,   // 显示列加载中
    menuloading: false,      // 菜单保存中
    menucloseloading: false, // 菜单关闭时,选择保存
    loading: false,          // 加载中,页面spin
@@ -64,10 +77,15 @@
    originConfig: null,      // 原配置
    originActions: null,     // 原始按钮信息,使用已有用户模板
    delActions: [],          // 删除按钮列表
    funcLoading: false,      // 存储过程创建中
    copyActions: [],         // 复制按钮组
    showColumnName: false,   // 显示列字段名控制
    tabviews: [],            // 所有标签页
    profileVisible: false    // 验证信息模态框
    profileVisible: false,   // 验证信息模态框
    optionLibs: null,        // 自定义下拉选项库
    thawBtnVisible: false,   // 解冻按钮弹窗
    thawbtnlist: null,       // 解冻按钮列表
    thawButtons: [],         // 已选择要解冻的按钮
    activeKey: '0'           // 默认展开基本信息
  }
  /**
@@ -76,25 +94,40 @@
   * 2、设置操作类型、原始菜单信息(每次保存后重置)、已使用表及基本信息表单
   */
  UNSAFE_componentWillMount () {
    const { config } = this.props
    const { config, editTab, editSubTab, optionLibs } = this.props
    let _config = null
    if (!config || config.create) {
    if (!config) {
      _config = JSON.parse(JSON.stringify(Source.baseConfig))
      if (config.uuid) {
        _config.uuid = config.uuid
        _config.tabName = config.label
      }
      _config.uuid = editSubTab ? editSubTab.linkTab : editTab.linkTab
      _config.tabName = editSubTab ? editSubTab.label : editTab.label
      _config.isAdd = true
    } else {
      _config = JSON.parse(JSON.stringify(config))
      _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 = []
    if (_config.type === 'user') {
      _config.action = _config.action.map(item => {
        let uuid = Utils.getuuid()
        if (item.OpenType === 'pop') { // 含有子配置项的按钮
          _oriActions.push({
            prebtn: JSON.parse(JSON.stringify(item)),
@@ -104,21 +137,24 @@
        }
        item.uuid = uuid
        return item
      })
    }
    let _activeKey =  editSubTab ? editSubTab.activeKey : editTab.activeKey
    this.setState({
      originActions: _oriActions,
      optionLibs: optionLibs,
      config: _config,
      activeKey: _activeKey || '0',
      originConfig: _config,
      selectedTables: _config.tables || [],
      menuformlist: [
        {
          type: 'text',
          key: 'tabName',
          label: this.state.dict['header.menu.tabName'],
          label: this.state.dict['header.menu.viewName'],
          initVal: _config.tabName,
          required: true,
          readonly: false
@@ -151,7 +187,7 @@
  componentDidMount () {
    let param = {
      func: 'sPC_Get_SelectedList',
      LText: 'select TbName ,Remark from sDataDictionary where IsKey!=\'\' and Deleted =0',
      LText: queryTableSql,
      obj_name: 'data',
      arr_field: 'TbName,Remark'
    }
@@ -254,6 +290,52 @@
            }
          })
        })
      } else {
        notification.warning({
          top: 92,
          message: res.message,
          duration: 10
        })
      }
    })
  }
  /**
   * @description 加载或刷新标签信息
   */
  reloadTab = () => {
    this.setState({
      loading: true,
      tabviews: []
    })
    Api.getSystemConfig({func: 'sPC_Get_UserTemp', TypeCharTwo: 'tab'}).then(res => {
      if (res.status) {
        this.setState({
          loading: false,
          tabviews: res.UserTemp.map(temp => {
            return {
              uuid: temp.MenuID,
              value: temp.MenuID,
              text: temp.MenuName,
              type: temp.Template,
              MenuNo: temp.MenuNo
            }
          })
        })
        notification.success({
          top: 92,
          message: '刷新成功。',
          duration: 2
        })
      } else {
        this.setState({
          loading: false
        })
        notification.warning({
          top: 92,
          message: res.message,
          duration: 10
        })
      }
    })
  }
@@ -262,687 +344,194 @@
   * @description 组件销毁,清除state更新
   */
  componentWillUnmount () {
    this.setState = (state, callback) => {
    this.setState = () => {
      return
    }
  }
  // 页面返回
  handleViewBack = () => {
    const {menu, editTab, tabConfig, editSubTab, btnTab, btnTabConfig} = this.props
    let _tabview = menu ? menu.LongParam.Template : ''
    let _subconfig = null
    if (editSubTab) {
      _subconfig = tabConfig
      if (editTab.hasOwnProperty('OpenType')) {
        _tabview = editTab.tabType
      } else {
        _tabview = editTab.type
      }
    } else if (!editSubTab && btnTab) {
      _tabview = btnTab.tabTemplate
      _subconfig = btnTabConfig
    }
    let param = {
      editMenu: menu,
      optionLibs: this.state.optionLibs,
      editTab: editSubTab ? editTab : null,
      tabConfig: null,
      editSubTab: null,
      subTabConfig: null,
      btnTab: btnTab,
      btnTabConfig: btnTabConfig,
      editAction: null,
      subConfig: _subconfig,
      tabview: _tabview
    }
    this.state.copyActions.forEach(item => {
      let _param = {
        func: 'sPC_MainMenu_Del',
        MenuID: item
      }
      Api.getSystemConfig(_param)
    })
    this.props.handleView(param)
  }
  /**
   * @description 元素添加或拖动时顺序变化
   */
  handleList = (type, list, card) => {
    const { config } = this.state
    if (list.length > config[type].length) {
      list = list.filter(item => !item.origin)
      this.setState({
        [type + 'loading']: true,
        config: {...config, [type]: list }
      }, () => {
        // 刷新对应的配置信息
        this.setState({
          [type + 'loading']: false
        })
        if (type === 'search') {
          this.handleSearch(card)
        } else if (type === 'action') {
          this.handleAction(card)
        } else if (type === 'columns') {
          this.handleColumn(card)
        }
      })
    } else {
      this.setState({config: {...config, [type]: list}})
      if (type === 'search') {
        this.handleSearch(card)
      } else if (type === 'action') {
        this.handleAction(card)
      } else if (type === 'columns') {
        this.handleColumn(card)
      }
    }
    this.setState({config: {...config, [type]: list}})
  }
  /**
   * @description 搜索条件编辑,获取搜索条件表单信息
   */
  handleSearch = (card) => {
    this.setState({
      visible: true,
      formtemp: 'search',
      modalTitle: '编辑-搜索条件',
      modaltype: 'search',
      card: card,
      formlist: [
        {
          type: 'text',
          key: 'label',
          label: this.state.dict['header.form.name'],
          initVal: card.label,
          required: true,
          readonly: false
        },
        {
          type: 'text',
          key: 'field',
          label: this.state.dict['header.form.field'],
          initVal: card.field,
          tooltip: '字段名可以使用逗号分隔,进行多字段综合搜索,注:综合搜索仅在文本类型时有效',
          tooltipClass: 'middle',
          required: true,
          readonly: false
        },
        {
          type: 'select',
          key: 'type',
          label: this.state.dict['header.form.type'],
          initVal: card.type,
          required: true,
          options: [{
            value: 'text',
            text: this.state.dict['header.form.text']
          }, {
            value: 'select',
            text: this.state.dict['header.form.select']
          }, {
            value: 'multiselect',
            text: this.state.dict['header.form.multiselect']
          }, {
            value: 'link',
            text: this.state.dict['header.form.link']
          }, {
            value: 'date',
            text: this.state.dict['header.form.dateday']
          }, {
            value: 'dateweek',
            text: this.state.dict['header.form.dateweek']
          }, {
            value: 'datemonth',
            text: this.state.dict['header.form.datemonth']
          }, {
            value: 'daterange',
            text: this.state.dict['header.form.daterange']
          }]
        },
        {
          type: 'text',
          key: 'initval',
          label: this.state.dict['header.form.initval'],
          initVal: card.initval,
          required: false
        },
        {
          type: 'radio',
          key: 'resourceType',
          label: this.state.dict['header.form.resourceType'],
          initVal: card.resourceType || '0',
          required: true,
          options: [{
            value: '0',
            text: this.state.dict['header.form.custom']
          }, {
            value: '1',
            text: this.state.dict['header.form.datasource']
          }]
        },
        {
          type: 'radio',
          key: 'setAll',
          label: this.state.dict['header.form.setAll'],
          initVal: card.setAll || 'false',
          options: [{
            value: 'true',
            text: this.state.dict['header.form.true']
          }, {
            value: 'false',
            text: this.state.dict['header.form.false']
          }]
        },
        {
          type: 'textarea',
          key: 'dataSource',
          label: this.state.dict['header.form.datasource'],
          initVal: card.dataSource || '',
          required: true,
          readonly: false
        },
        {
          type: 'options',
          key: 'options',
          label: '',
          initVal: card.options || [],
          required: true,
          readonly: false
        },
        {
          type: 'text',
          key: 'linkField',
          label: this.state.dict['header.form.linkField'],
          initVal: card.linkField || '',
          required: true,
          readonly: false
        },
        {
          type: 'text',
          key: 'valueField',
          label: this.state.dict['header.form.valueField'],
          initVal: card.valueField || '',
          required: true,
          readonly: false
        },
        {
          type: 'text',
          key: 'valueText',
          label: this.state.dict['header.form.valueText'],
          initVal: card.valueText || '',
          required: true,
          readonly: false
        },
        {
          type: 'text',
          key: 'orderBy',
          label: this.state.dict['header.form.orderBy'],
          initVal: card.orderBy || '',
          required: false,
          readonly: false
        },
        {
          type: 'select',
          key: 'orderType',
          label: this.state.dict['header.form.orderType'],
          initVal: card.orderType || 'asc',
          options: [{
            value: 'asc',
            text: this.state.dict['header.form.asc']
          }, {
            value: 'desc',
            text: this.state.dict['header.form.desc']
          }]
        },
        {
          type: 'select',
          key: 'match',
          label: this.state.dict['header.form.match'],
          initVal: card.match || 'like',
          required: true,
          options: [{
            value: 'like',
            text: 'like'
          }, {
            value: 'equal',
            text: 'equal'
          }, {
            value: 'greater',
            text: '>'
          }, {
            value: 'less',
            text: '<'
          }, {
            value: 'greaterequal',
            text: '>='
          }]
        },
        {
          type: 'select',
          key: 'display',
          label: this.state.dict['header.form.display'],
          initVal: card.display || 'dropdown',
          required: true,
          options: [{
            value: 'dropdown',
            text: this.state.dict['header.form.dropdown']
          }, {
            value: 'button',
            text: this.state.dict['header.form.button']
          }]
        }
      ]
      formlist: getSearchForm(card, this.props.sysRoles)
    })
  }
  /**
   * @description 按钮编辑,获取按钮表单信息
   */
  handleAction = (card, type) => {
    let ableField = this.props.permFuncField.join(', ')
    let functip = <div>
      <p style={{marginBottom: '5px'}}>{this.state.dict['header.modal.func.innerface'].replace('@ableField', ableField)}</p>
      <p>{this.state.dict['header.modal.func.outface']}</p>
    </div>
    this.setState({
      visible: true,
      formtemp: 'action',
      modalTitle: type === 'copy' ? '复制-按钮' : '编辑-按钮',
      modaltype: type === 'copy' ? 'actionCopy' : 'actionEdit',
      card: card,
      formlist: [
        {
          type: 'text',
          key: 'label',
          label: this.state.dict['header.form.name'],
          initVal: card.label,
          required: true,
          readonly: false
        },
        {
          type: 'select',
          key: 'OpenType',
          label: this.state.dict['header.form.openType'],
          initVal: card.OpenType,
          required: true,
          options: [{
            value: 'pop',
            text: this.state.dict['header.form.popform']
          }, {
            value: 'prompt',
            text: this.state.dict['header.form.prompt']
          }, {
            value: 'exec',
            text: this.state.dict['header.form.exec']
          }, {
            value: 'excelIn',
            text: this.state.dict['header.form.excelIn']
          }, {
            value: 'excelOut',
            text: this.state.dict['header.form.excelOut']
          }, {
            value: 'popview',
            text: this.state.dict['header.form.popview']
          }]
        }, {
          type: 'select',
          key: 'tabType',
          label: this.state.dict['header.form.tabType'],
          initVal: card.tabType || 'SubTable',
          required: true,
          options: [{
            value: 'SubTable',
            text: this.state.dict['header.menu.tab.subtable']
          }]
        },
        {
          type: 'select',
          key: 'linkTab',
          label: '关联标签',
          initVal: card.linkTab || '',
          required: false,
          options: []
        },
        {
          type: 'radio',
          key: 'intertype',
          label: this.state.dict['header.form.intertype'],
          initVal: card.intertype,
          required: true,
          options: [{
            value: 'inner',
            text: this.state.dict['header.form.interface.inner']
          }, {
            value: 'outer',
            text: this.state.dict['header.form.interface.outer']
          }]
        },
        {
          type: 'text',
          key: 'innerFunc',
          label: this.state.dict['header.form.innerFunc'],
          initVal: card.innerFunc,
          tooltip: <div>
            <p>内部接口: 可自定义数据处理函数,函数名称需以{ableField}等字符开始;未设置时会调用系统函数,使用系统函数需完善数据源及操作类型;</p>
            <p>外部接口: 可自定义数据处理函数,提交数据经过内部函数处理后,传入外部接口,未设置时,数据会直接传入外部接口。</p>
          </div>,
          fields: this.props.permFuncField,
          tooltipClass: 'middle',
          required: false,
          readonly: false
        },
        {
          type: 'radio',
          key: 'sysInterface',
          label: this.state.dict['header.form.sysInterface'],
          initVal: card.sysInterface || 'false',
          required: true,
          options: [{
            value: 'true',
            text: this.state.dict['header.form.true']
          }, {
            value: 'false',
            text: this.state.dict['header.form.false']
          }]
        },
        {
          type: 'text',
          key: 'outerFunc',
          label: this.state.dict['header.form.outerFunc'],
          initVal: card.outerFunc,
          required: false,
          readonly: false
        },
        {
          type: 'text',
          key: 'interface',
          label: this.state.dict['header.form.interface'],
          initVal: card.sysInterface === 'true' ? (window.GLOB.mainSystemApi || window.GLOB.subSystemApi) : card.interface,
          required: true,
          readonly: card.sysInterface === 'true'
        },
        {
          type: 'text',
          key: 'callbackFunc',
          label: this.state.dict['header.form.callbackFunc'],
          initVal: card.callbackFunc,
          required: false,
          readonly: false
        },
        {
          type: 'select',
          key: 'position',
          label: this.state.dict['header.form.position'],
          initVal: card.position || 'toolbar',
          required: true,
          options: [{
            value: 'toolbar',
            text: this.state.dict['header.form.toolbar']
          }, {
            value: 'grid',
            text: this.state.dict['header.form.grid']
          }]
        },
        {
          type: 'select',
          key: 'Ot',
          label: this.state.dict['header.form.isRequired'],
          initVal: card.Ot || 'requiredSgl',
          required: true,
          options: []
        },
        {
          type: 'select',
          key: 'execSuccess',
          label: this.state.dict['header.form.execSuccess'],
          initVal: card.execSuccess || 'never',
          required: true,
          options: [{
            value: 'never',
            text: this.state.dict['header.form.refresh.never']
          }, {
            value: 'grid',
            text: this.state.dict['header.form.refresh.grid']
          }, {
            value: 'view',
            text: this.state.dict['header.form.refresh.view']
          }]
        },
        {
          type: 'select',
          key: 'execError',
          label: this.state.dict['header.form.execError'],
          initVal: card.execError || 'never',
          required: true,
          options: [{
            value: 'never',
            text: this.state.dict['header.form.refresh.never']
          }, {
            value: 'grid',
            text: this.state.dict['header.form.refresh.grid']
          }, {
            value: 'view',
            text: this.state.dict['header.form.refresh.view']
          }]
        },
        {
          type: 'select',
          key: 'popClose',
          label: this.state.dict['header.form.popClose'],
          initVal: card.popClose || 'never',
          required: true,
          options: [{
            value: 'never',
            text: this.state.dict['header.form.refresh.never']
          }, {
            value: 'maingrid',
            text: this.state.dict['header.form.refresh.maingrid']
          }, {
            value: 'subgrid',
            text: this.state.dict['header.form.refresh.subgrid']
          }]
        },
        {
          type: 'select',
          key: 'icon',
          label: this.state.dict['header.form.icon'],
          initVal: card.icon,
          required: false,
          options: []
        },
        {
          type: 'select',
          key: 'class',
          label: this.state.dict['header.form.class'],
          initVal: card.class,
          required: false,
          options: []
        },
        {
          type: 'text',
          key: 'sql',
          label: this.state.dict['header.form.datasource'],
          initVal: card.sql || this.state.config.setting.tableName || '',
          tooltip: this.state.dict['header.form.actionhelp.datasource'],
          required: false
        },
        {
          type: 'select',
          key: 'sqlType',
          label: this.state.dict['header.form.action.type'],
          initVal: card.sqlType || '',
          tooltip: this.state.dict['header.form.actionhelp.sqlType'],
          required: false,
          options: []
        }
      ]
      formlist: getActionForm(card, functip, this.state.config, this.props.permFuncField)
    })
  }
  /**
   * @description 显示列与合并列编辑,获取表单信息
   */
  handleColumn = (card) => {
    const { menu } = this.props
    if (card.type !== 'colspan') {
      this.setState({
        visible: true,
        formtemp: 'columns',
        modalTitle: '编辑-显示列',
        card: card,
        formlist: [
          {
            type: 'text',
            key: 'label',
            label: this.state.dict['header.form.name'],
            initVal: card.label,
            required: true
          },
          {
            type: 'text',
            key: 'field',
            label: this.state.dict['header.form.field'],
            initVal: card.field,
            required: true,
            readonly: false
          },
          {
            type: 'select',
            key: 'type',
            label: this.state.dict['header.form.type'],
            initVal: card.type,
            required: true,
            options: [{
              value: 'text',
              text: this.state.dict['header.form.text']
            }, {
              value: 'picture',
              text: this.state.dict['header.form.picture']
            }, {
              value: 'number',
              text: this.state.dict['header.form.number']
            }, {
              value: 'textarea',
              text: this.state.dict['header.form.textarea']
            }]
          },
          {
            type: 'select',
            key: 'Align',
            label: this.state.dict['header.form.align'],
            initVal: card.Align,
            required: true,
            options: [{
              value: 'left',
              text: this.state.dict['header.form.alignLeft']
            }, {
              value: 'right',
              text: this.state.dict['header.form.alignRight']
            }, {
              value: 'center',
              text: this.state.dict['header.form.alignCenter']
            }]
          },
          {
            type: 'radio',
            key: 'Hide',
            label: this.state.dict['header.form.Hide'],
            initVal: card.Hide,
            required: true,
            options: [{
              value: 'true',
              text: this.state.dict['header.form.true']
            }, {
              value: 'false',
              text: this.state.dict['header.form.false']
            }]
          },
          {
            type: 'radio',
            key: 'IsSort',
            label: this.state.dict['header.form.IsSort'],
            initVal: card.IsSort,
            required: true,
            options: [{
              value: 'true',
              text: this.state.dict['header.form.true']
            }, {
              value: 'false',
              text: this.state.dict['header.form.false']
            }]
          },
          {
            type: 'number',
            key: 'Width',
            min: 1,
            max: 1000,
            decimal: 0,
            label: this.state.dict['header.form.columnWidth'],
            initVal: card.Width,
            required: true
          },
          {
            type: 'number',
            key: 'decimal',
            min: 0,
            max: 18,
            decimal: 0,
            label: this.state.dict['header.form.decimal'],
            initVal: card.decimal,
            required: false
          },
          {
            type: 'select',
            key: 'format',
            label: this.state.dict['header.form.format'],
            initVal: card.format || '',
            options: [{
              value: '',
              text: this.state.dict['header.form.empty']
            }, {
              value: 'thdSeparator',
              text: this.state.dict['header.form.thdSeparator']
            }],
            required: false
          },
          {
            type: 'text',
            key: 'prefix',
            label: this.state.dict['header.form.prefix'],
            initVal: card.prefix || '',
            required: false,
            readonly: false
          },
          {
            type: 'text',
            key: 'postfix',
            label: this.state.dict['header.form.postfix'],
            initVal: card.postfix || '',
            // tooltip: '后缀值设置为"\\n",表示换行',
            tooltipClass: 'middle',
            required: false,
            readonly: false
          },
          {
            type: 'select',
            key: 'match',
            label: this.state.dict['header.form.match'],
            initVal: card.match || '',
            options: [{
              value: '',
              text: this.state.dict['header.form.empty']
            }, {
              value: '>',
              text: '>'
            }, {
              value: '<',
              text: '<'
            }, {
              value: '>=',
              text: '>='
            }, {
              value: '<=',
              text: '<='
            }],
            required: false
          },
          {
            type: 'text',
            key: 'matchVal',
            min: -Infinity,
            max: Infinity,
            decimal: 0,
            label: this.state.dict['header.form.matchVal'],
            initVal: card.matchVal || '',
            required: false,
            readonly: false
          },
          {
            type: 'select',
            key: 'color',
            label: this.state.dict['header.form.color'],
            initVal: card.color || '',
            options: [{
              value: '',
              text: this.state.dict['header.form.empty']
            }, {
              value: 'red',
              text: '红色(内容)'
            }, {
              value: 'redbg',
              text: '红色(背景)'
            }, {
              value: 'orange',
              text: '橙色(内容)'
            }, {
              value: 'orangebg',
              text: '橙色(背景)'
            }, {
              value: 'green',
              text: '绿色(内容)'
            }, {
              value: 'greenbg',
              text: '绿色(背景)'
            }],
            required: false
          }
        ]
      let menulist = menu.fstMenuList.map(item => {
        return {
          value: item.MenuID,
          label: item.text,
          isLeaf: false
        }
      })
      if ((card.type === 'text' || card.type === 'number') && card.linkmenu && card.linkmenu.length > 0) {
        let _param = {
          func: 'sPC_Get_FunMenu',
          ParentID: card.linkmenu[0],
          systemType: options.systemType,
          debug: 'Y'
        }
        this.setState({
          loading: true
        })
        Api.getSystemConfig(_param).then(result => {
          if (result.status) {
            menulist = menulist.map(item => {
              if (item.value === card.linkmenu[0]) {
                item.children = result.data.map(item => {
                  let submenu = {
                    value: item.ParentID,
                    label: item.MenuNameP,
                    children: item.FunMenu.map(cell => {
                      return {
                        value: cell.MenuID,
                        label: cell.MenuName,
                        MenuID: cell.MenuID,
                        MenuName: cell.MenuName,
                        MenuNo: cell.MenuNo,
                        Ot: cell.Ot,
                        PageParam: cell.PageParam,
                        LinkUrl: cell.LinkUrl,
                        disabled: cell.MenuID === menu.MenuID
                      }
                    })
                  }
                  return submenu
                })
              }
              return item
            })
          } else {
            notification.warning({
              top: 92,
              message: result.message,
              duration: 10
            })
          }
          this.setState({
            loading: false,
            modaltype: 'columns',
            card: card,
            formlist: getColumnForm(card, this.props.sysRoles, menulist)
          })
        })
      } else {
        this.setState({
          modaltype: 'columns',
          card: card,
          formlist: getColumnForm(card, this.props.sysRoles, menulist)
        })
      }
    } else {
      this.setState({
        visible: true,
        formtemp: 'columns',
        modaltype: 'colspan',
        card: card
      })
    }
  }
  /**
   * @description 操作列编辑
   */
  handleGridBtn = () => {
    this.setState({
      visible: true,
      formtemp: 'gridbtn',
      modalTitle: '编辑-操作列',
      modaltype: 'gridbtn'
    })
  }
@@ -953,28 +542,121 @@
   * 3、添加或编辑列,保存时,如按钮位置设置为表格,则修改操作列显示状态
   */
  handleSubmit = () => {
    const { card } = this.state
    let _config = JSON.parse(JSON.stringify(this.state.config))
    const { card, config, modaltype, optionLibs } = this.state
    if (this.state.formtemp !== 'gridbtn') {
      this.formRef.handleConfirm().then(res => {
        let isupdate = false
    if (modaltype === 'search') {
      this.searchFormRef.handleConfirm().then(res => {
        if ( // 更新下拉字典
          (res.type === 'select' || res.type === 'multiselect' || res.type === 'link') &&
          res.resourceType === '0' &&
          res.options && res.options.length > 0
        ) {
          optionLibs.set(config.uuid + res.uuid, {
            uuid: config.uuid + res.uuid,
            label: res.label,
            parname: config.tabName,
            type: 'search',
            options: res.options
          })
        }
        if (res.type === 'action' && card.originCard && res.values.OpenType === 'pop') {
        let fieldrepet = false // 字段重复
        let labelrepet = false // 提示文字重复
        let _search = config.search.map(item => {
          if (item.uuid !== res.uuid && res.field && item.field) {
            if (item.field === res.field) {
              fieldrepet = true
            } else if (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
        }
        _search = _search.filter(item => !item.origin)
        this.setState({
          config: {...config, search: _search},
          optionLibs: optionLibs,
          modaltype: ''
        })
      })
    } else if (modaltype === 'actionEdit' || modaltype === 'actionCopy') {
      this.actionFormRef.handleConfirm().then(res => {
        let _action = config.action.map(item => {
          if (item.uuid === res.uuid) {
            return res
          } else {
            return item
          }
        })
        _action = _action.filter(item => !item.origin)
        if (modaltype === 'actionCopy') {
          _action.push(res)
        }
        // 复制按钮前后皆为表单时,复制表单配置信息,id存于复制列表
        if (res.OpenType === 'pop' && card.originCard && card.originCard.OpenType === 'pop') {
          Api.getSystemConfig({
            func: 'sPC_Get_LongParam',
            MenuID: card.originCard.uuid
          }).then(result => {
            if (result.status && result.LongParam) {
              let _LongParam = ''
              // 解析配置,修改模态框标题名称
              if (result.LongParam) {
                try {
                  _LongParam = JSON.parse(window.decodeURIComponent(window.atob(result.LongParam)))
                } catch (e) {
                  console.warn('Parse Failure')
                  _LongParam = ''
                }
              }
              if (_LongParam && _LongParam.type === 'Modal') {
                try {
                  _LongParam.setting.title = res.label
                  _LongParam = window.btoa(window.encodeURIComponent(JSON.stringify(_LongParam)))
                } catch {
                  console.warn('Stringify Failure')
                  _LongParam = ''
                }
              } else {
                _LongParam = ''
              }
              let param = {
                func: 'sPC_ButtonParam_AddUpt',
                ParentID: _config.uuid,
                MenuID: res.values.uuid,
                MenuNo: _config.tabNo,
                ParentID: config.uuid,
                MenuID: res.uuid,
                MenuNo: config.tabNo,
                Template: 'Modal',
                MenuName: res.values.label,
                MenuName: res.label,
                PageParam: JSON.stringify({Template: 'Modal'}),
                LongParam: result.LongParam
                LongParam: _LongParam
              }
              Api.getSystemConfig(param).then(response => {
                if (!response.status) {
@@ -983,73 +665,125 @@
                    message: response.message,
                    duration: 10
                  })
                } else {
                  this.setState({
                    copyActions: [...this.state.copyActions, res.uuid]
                  })
                }
              })
            }
          })
        }
        _config[res.type] = _config[res.type].map(item => {
          if (item.uuid === res.values.uuid) {
            isupdate = true
            return res.values
        // 判断是否存在操作列
        let _hasGridbtn = _action.filter(act => act.position === 'grid').length > 0
        let _gridBtn = config.gridBtn
        if (_gridBtn) {
          _gridBtn.display = _hasGridbtn
        } else {
          _gridBtn = {
            display: _hasGridbtn,
            Align: 'center',
            IsSort: 'false',
            uuid: Utils.getuuid(),
            label: this.state.dict['header.form.column.action'],
            type: 'action',
            style: 'button',
            show: 'horizontal',
            Width: 120
          }
        }
        this.setState({
          config: {...config, action: _action, gridBtn: _gridBtn},
          modaltype: ''
        })
      })
    } else if (modaltype === 'columns' || modaltype === 'colspan') {
      this.columnFormRef.handleConfirm().then(res => {
        let fieldrepet = false // 字段重复
        let labelrepet = false // 提示文字重复
        let _columns = config.columns.map(item => {
          if (item.uuid !== res.uuid && res.field && item.field) {
            if (item.field === res.field) {
              fieldrepet = true
            } else if (item.label === res.label) {
              labelrepet = true
            }
          }
          if (item.uuid === res.uuid) {
            return res
          } else {
            return item
          }
        })
        _config[res.type] = _config[res.type].filter(item => !item.origin)
        if (!isupdate) { // 操作不是修改,添加元素至列表
          _config[res.type].push(res.values)
        }
        if (res.type === 'action') {
          let gridbtn = _config.action.filter(act => act.position === 'grid')
          let _display = false
          if (gridbtn.length > 0) {
            _display = true
          }
          if (_config.gridBtn) {
            _config.gridBtn.display = _display
          } else {
            _config.gridBtn = {
              display: _display,
              Align: 'center',
              IsSort: 'false',
              uuid: Utils.getuuid(),
              label: this.state.dict['header.form.column.action'],
              type: 'action',
              style: 'button',
              show: 'horizontal',
              Width: 120
            }
          }
        }
        this.setState({
          config: _config,
          searchloading: true,
          actionloading: true,
          columnsloading: true,
          visible: false
        }, () => {
          this.setState({
            searchloading: false,
            actionloading: false,
            columnsloading: false,
        if (fieldrepet) {
          notification.warning({
            top: 92,
            message: '字段已存在!',
            duration: 10
          })
        })
      })
    } else {
      this.formRef.handleConfirm().then(res => {
        _config.gridBtn = res
          return
        } else if (labelrepet) {
          notification.warning({
            top: 92,
            message: '名称已存在!',
            duration: 10
          })
          return
        }
        _columns = _columns.filter(item => !item.origin)
        this.setState({
          config: _config,
          visible: false
          config: {...config, columns: _columns},
          modaltype: ''
        })
      })
    } else if (modaltype === 'gridbtn') {
      this.gridBtnFormRef.handleConfirm().then(res => {
        this.setState({
          config: {...config, gridBtn: res},
          modaltype: ''
        })
      })
    }
  }
  /**
   * @description 取消保存,如果元素为新添元素,则从序列中删除
   */
  editModalCancel = () => {
    const { config, card, modaltype } = this.state
    if (card.focus) {
      let _config = null
      if (modaltype === 'search') {
        let _search = config.search.filter(item => item.uuid !== card.uuid)
        _config = {...config, search: _search}
      } else if (modaltype === 'actionEdit') {
        let _action = config.action.filter(item => item.uuid !== card.uuid)
        _config = {...config, action: _action}
      } else if (modaltype === 'columns' || modaltype === 'colspan') {
        let _columns = config.columns.filter(item => item.uuid !== card.uuid)
        _config = {...config, columns: _columns}
      } else {
        _config = config
      }
      this.setState({
        card: null,
        config: _config,
        modaltype: ''
      })
    } else {
      this.setState({
        card: null,
        modaltype: ''
      })
    }
  }
@@ -1060,13 +794,10 @@
  creatFunc = () => {
    let _config = JSON.parse(JSON.stringify(this.state.config))
    this.formRef.handleConfirm().then(res => {
      let btn = res.values  // 按钮信息
    this.actionFormRef.handleConfirm().then(res => {
      let btn = res         // 按钮信息
      let newLText = ''     // 创建存储过程sql
      let DelText = ''      // 删除存储过程sql
      let isExit = false    // 存储过程是否存在
      let sysTVPText = ''   // 已有的存储过程语句(云端)
      let localTVPText = '' // 已有的存储过程语句(本地)
      // 创建存储过程,必须填写内部函数名
      if (!btn.innerFunc) {
@@ -1078,11 +809,6 @@
        return
      }
      // 创建中
      this.setState({
        funcLoading: true
      })
      new Promise(resolve => {
        // 弹窗(表单)类按钮,先获取按钮配置信息,如果尚未配置按钮则会报错并终止。
        // 获取信息后生成删除和创建存储过程的语句
@@ -1093,10 +819,10 @@
          }).then(res => {
            let _LongParam = ''
            if (res.status && res.LongParam) {
              _LongParam = window.decodeURIComponent(window.atob(res.LongParam))
              try {
                _LongParam = JSON.parse(_LongParam)
                _LongParam = JSON.parse(window.decodeURIComponent(window.atob(res.LongParam)))
              } catch (e) {
                console.warn('Parse Failure')
                _LongParam = ''
              }
            }
@@ -1121,14 +847,40 @@
              DelText = Utils.formatOptions(Utils.dropfunc(_param.funcName))
              resolve(true)
            } else {
              resolve(false)
              notification.warning({
                top: 92,
                message: '弹窗(表单)按钮,请先配置表单信息!',
                duration: 10
              })
              resolve(false)
            }
          })
        } else if (btn.OpenType === 'excelIn') {
          if (btn.verify && btn.verify.sheet && btn.verify.columns && btn.verify.columns.length > 0) {
            let _param = {
              funcName: btn.innerFunc,
              menuNo: _config.tabNo
            }
            newLText = Utils.formatOptions(Utils.getexcelInfunc(_param, btn, {MenuID: _config.uuid, MenuName: _config.tabName}))
            DelText = Utils.formatOptions(Utils.dropfunc(_param.funcName))
            resolve(true)
          } else {
            notification.warning({
              top: 92,
              message: '请完善导入Excel验证信息!',
              duration: 10
            })
            resolve(false)
          }
        } else if (btn.OpenType === 'excelOut') {
          let _param = {
            innerFunc: btn.innerFunc
          }
          newLText = Utils.formatOptions(Utils.getTableFunc(_param, {MenuID: _config.uuid, MenuName: _config.tabName, MenuNo: _config.tabNo}, _config)) // 创建存储过程sql
          DelText = Utils.formatOptions(Utils.dropfunc(btn.innerFunc))
          resolve(true)
        } else {
          let _param = {
            funcName: btn.innerFunc,
@@ -1141,222 +893,41 @@
          resolve(true)
        }
      }).then(res => {
        // 获取云端及本地,是否已存在该存储过程的信息
        if (res === false) return res
        if (!res) return
        let sysDefer = new Promise(resolve => {
          Api.getSystemConfig({
            func: 'sPC_Get_TVP', // 云端获取存储结果
            TVPName: btn.innerFunc
          }).then(result => {
            resolve(result)
          })
        })
        this.refs.btnCreatFunc.exec(btn.innerFunc, newLText, DelText).then(result => {
          if (result !== 'success') return
        let localDefer = new Promise(resolve => {
          let _param = { // 获取本地存储过程信息
            func: 's_get_userproc',
            LText: btn.innerFunc
          }
          _param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss') + '.000'
          _param.secretkey = Utils.encrypt(_param.LText, _param.timestamp)
          Api.getLocalConfig(_param).then(result => {
            resolve(result)
          })
        })
        return Promise.all([sysDefer, localDefer])
      }).then(res => {
        // 云端结果与新语句不同时,更新云端信息
        if (res === false) return res
        let isError = false
        res.forEach((result, index) => {
          if (!result.status) {
            notification.warning({
              top: 92,
              message: result.message,
              duration: 10
            })
            isError = true
          } else if (index === 0) {
            sysTVPText = result.TVPText
          } else {
            if (result.Ltext) { // 本地存储过程是否存在
              isExit = true
          _config.action = _config.action.map(item => {
            if (item.uuid === btn.uuid) {
              return btn
            } else {
              return item
            }
            localTVPText = Utils.formatOptions(result.Ltext)
          }
        })
        if (isError) return false
        if ((newLText === localTVPText) && (newLText === sysTVPText)) {
          return 'drop'
        } else if (!localTVPText || (localTVPText === sysTVPText)) {
          // 本地存储过程不存在,将新的存储过程更新至云端
          return Api.getSystemConfig({
            func: 'sPC_TVP_InUp',
            TVPName: btn.innerFunc,
            TVPText: newLText,
            TypeName: 'P'
          })
        } else {
          return new Promise(resolve => {
            Api.getSystemConfig({ // 添加现有的本地存储过程至云端
              func: 'sPC_TVP_InUp',
              TVPName: btn.innerFunc,
              TVPText: localTVPText,
              TypeName: 'P'
            }).then(result => {
              if (result.status) {
                Api.getSystemConfig({
                  func: 'sPC_TVP_InUp', // 添加最新的存储过程至云端
                  TVPName: btn.innerFunc,
                  TVPText: newLText,
                  TypeName: 'P'
                }).then(response => {
                  resolve(response)
                })
              } else {
                resolve(result)
              }
            })
          })
        }
      }).then(res => {
        // 云端信息更新后,判断是删除或是直接新建存储过程
        if (res === false || res === 'drop') return res
          _config.action = _config.action.filter(item => !item.origin)
        if (!res.status) {
          notification.warning({
            top: 92,
            message: res.message,
            duration: 10
          })
          return false
        } else if (isExit) {
          return 'drop'
        } else {
          return 'create'
        }
      }).then(res => {
        // 删除存储过程
        if (res === false || res === 'create') return res
          // 判断是否存在操作列
          let _hasGridbtn = _config.action.filter(act => act.position === 'grid').length > 0
        let _param = {
          func: 'sPC_TableData_InUpDe',
          LText: DelText,
          TypeCharOne: 'proc' // 删除或创建存储过程
        }
        _param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss') + '.000'
        _param.secretkey = Utils.encrypt(_param.LText, _param.timestamp)
        return Api.getLocalConfig(_param)
      }).then(res => {
        // 根据上述操作结果,判断是否新建存储过程
        if (res === false || res === 'create') return res
        if (!res.status) {
          notification.warning({
            top: 92,
            message: res.message,
            duration: 10
          })
          return false
        } else {
          return 'create'
        }
      }).then(res => {
        // 新建存储过程
        if (res === false) return res
        let _param = {
          func: 'sPC_TableData_InUpDe',
          LText: newLText,
          TypeCharOne: 'proc' // 删除或创建存储过程
        }
        _param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss') + '.000'
        _param.secretkey = Utils.encrypt(_param.LText, _param.timestamp)
        return Api.getLocalConfig(_param)
      }).then(res => {
        // 处理新建结果
        if (res === false) return res
        if (!res.status) {
          notification.warning({
            top: 92,
            message: res.message,
            duration: 10
          })
          return false
        } else {
          notification.success({
            top: 92,
            message: '创建成功',
            duration: 2
          })
          return true
        }
      }).then(res => {
        // 新建成功后,更新页面按钮信息
        if (res === false) {
          this.setState({
            funcLoading: false
          })
          return
        }
        let isupdate = false
        _config.action = _config.action.map(item => {
          if (item.uuid === btn.uuid) {
            isupdate = true
            return btn
          if (_config.gridBtn) {
            _config.gridBtn.display = _hasGridbtn
          } else {
            return item
            _config.gridBtn = {
              display: _hasGridbtn,
              Align: 'center',
              IsSort: 'false',
              uuid: Utils.getuuid(),
              label: this.state.dict['header.form.column.action'],
              type: 'action',
              style: 'button',
              show: 'horizontal',
              Width: 120
            }
          }
        })
        _config.action = _config.action.filter(item => !item.origin)
        if (!isupdate) { // 操作不是修改,添加元素至列表
          _config.action.push(btn)
        }
        let gridbtn = _config.action.filter(act => act.position === 'grid')
        let _display = false
        if (gridbtn.length > 0) {
          _display = true
        }
        if (_config.gridBtn) {
          _config.gridBtn.display = _display
        } else {
          _config.gridBtn = {
            display: _display,
            Align: 'center',
            IsSort: 'false',
            uuid: Utils.getuuid(),
            label: this.state.dict['header.form.column.action'],
            type: 'action',
            style: 'button',
            show: 'horizontal',
            Width: 120
          }
        }
        this.setState({
          config: _config,
          actionloading: true,
          funcLoading: false
        }, () => {
          this.setState({
            actionloading: false
            config: _config,
          })
        })
      })
@@ -1367,10 +938,10 @@
   * @description 创建表格存储过程
   */
  tableCreatFunc = () => {
    let config = JSON.parse(JSON.stringify(this.state.config))
    const { config } = this.state
    this.settingRef.handleConfirm().then(res => {
      const setting = res
    this.settingRef.handleConfirm().then(setting => {
      if (!(setting.interType === 'inner') || !setting.innerFunc) {
        notification.warning({
          top: 92,
@@ -1380,210 +951,23 @@
        return
      }
      if (setting.dataresource.length > 50 && config.setting.dataresource !== setting.dataresource) {
        let param = {
          func: 's_DataSrc_Save',
          LText: setting.dataresource,
          MenuID: config.uuid
        }
        param.LText = Utils.formatOptions(param.LText)
        param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss') + '.000'
        param.secretkey = Utils.encrypt(param.LText, param.timestamp)
        Api.getLocalConfig(param)
      }
      this.setState({
        funcLoading: true
      })
      let newLText = Utils.formatOptions(Utils.getTableFunc(setting, {MenuID: config.uuid, MenuName: config.tabName, MenuNo: config.tabNo}, config)) // 创建存储过程sql
      let _config = {...config, setting: setting}
      let newLText = Utils.formatOptions(Utils.getTableFunc(setting, {MenuID: _config.uuid, MenuName: _config.tabName, MenuNo: _config.tabNo}, _config)) // 创建存储过程sql
      let DelText = Utils.formatOptions(Utils.dropfunc(setting.innerFunc))          // 删除存储过程sql
      new Promise(resolve => {
        let sysDefer = new Promise(resolve => {
          Api.getSystemConfig({
            func: 'sPC_Get_TVP', // 云端获取存储结果
            TVPName: setting.innerFunc
          }).then(result => {
            if (!result.status) {
              notification.warning({
                top: 92,
                message: result.message,
                duration: 10
              })
              resolve(false)
            } else {
              resolve(result)
            }
          })
        })
        let localDefer = new Promise(resolve => {
          let _param = { // 获取本地存储过程信息
            func: 's_get_userproc',
            LText: setting.innerFunc
          }
          _param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss') + '.000'
          _param.secretkey = Utils.encrypt(_param.LText, _param.timestamp)
          Api.getLocalConfig(_param).then(result => {
            if (!result.status) {
              notification.warning({
                top: 92,
                message: result.message,
                duration: 10
              })
              resolve(false)
            } else {
              resolve(result)
            }
          })
        })
        Promise.all([sysDefer, localDefer]).then(result => {
          resolve(result)
        })
      }).then(res => {
        // 获取云端及本地,是否已存在该存储过程的信息
        if (res === false) return res
        if (res[0] === false || res[1] === false) return false
        let cloudfunc = ''
        let localfunc = ''
        res.forEach((item, index) => {
          if (index === 0 && item.TVPText) {
            cloudfunc = item.TVPText
          } else if (index === 1 && item.Ltext) {
            localfunc = Utils.formatOptions(item.Ltext)
          }
        })
        if ((newLText === localfunc) && (newLText === cloudfunc)) {
          return 'drop'
        } else if (!localfunc || (cloudfunc === localfunc)) {
          // 本地存储过程不存在,或云端和本地存储过程一致时,将新的存储过程更新至云端
          return Api.getSystemConfig({
            func: 'sPC_TVP_InUp',
            TVPName: setting.innerFunc,
            TVPText: newLText,
            TypeName: 'P'
          })
        } else {
          return new Promise(resolve => {
            Api.getSystemConfig({ // 添加现有的本地存储过程至云端
              func: 'sPC_TVP_InUp',
              TVPName: setting.innerFunc,
              TVPText: localfunc,
              TypeName: 'P'
            }).then(result => {
              if (result.status) {
                Api.getSystemConfig({
                  func: 'sPC_TVP_InUp', // 添加最新的存储过程至云端
                  TVPName: setting.innerFunc,
                  TVPText: newLText,
                  TypeName: 'P'
                }).then(response => {
                  resolve(response)
                })
              } else {
                resolve(result)
              }
            })
          })
        }
      }).then(res => {
        // 云端信息更新后,判断是删除或是直接新建存储过程
        if (res === false || res === 'drop') return res
        if (!res.status) {
          notification.warning({
            top: 92,
            message: res.message,
            duration: 10
          })
          return false
        } else {
          return 'create'
        }
      }).then(res => {
        // 删除存储过程
        if (res === false || res === 'create') return res
        let _param = {
          func: 'sPC_TableData_InUpDe',
          LText: DelText,
          TypeCharOne: 'proc' // 删除或创建存储过程
        }
        _param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss') + '.000'
        _param.secretkey = Utils.encrypt(_param.LText, _param.timestamp)
        return Api.getLocalConfig(_param)
      }).then(res => {
        // 根据上述操作结果,判断是否新建存储过程
        if (res === false || res === 'create') return res
        if (!res.status) {
          notification.warning({
            top: 92,
            message: res.message,
            duration: 10
          })
          return false
        } else {
          return 'create'
        }
      }).then(res => {
        // 新建存储过程
        if (res === false) return res
        let _param = {
          func: 'sPC_TableData_InUpDe',
          LText: newLText,
          TypeCharOne: 'proc' // 删除或创建存储过程
        }
        _param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss') + '.000'
        _param.secretkey = Utils.encrypt(_param.LText, _param.timestamp)
        return Api.getLocalConfig(_param)
      }).then(res => {
        // 处理新建结果
        if (res === false) return res
        if (!res.status) {
          notification.warning({
            top: 92,
            message: res.message,
            duration: 10
          })
          return false
        } else {
          notification.success({
            top: 92,
            message: '创建成功',
            duration: 2
          })
          return true
        }
      }).then(res => {
        // 新建成功后,更新页面按钮信息
        if (res === false) {
      this.refs.tableCreatFunc.exec(setting.innerFunc, newLText, DelText).then(result => {
        if (result === 'success') {
          this.setState({
            funcLoading: false
            config: _config
          })
          return
        }
        this.setState({
          config: {...config, setting: setting}
        })
      })
    })
  }
  deleteElement = (element) => {
    const { thawButtons } = this.state
    let _this = this
    confirm({
      content: `确定删除<<${element.card.label}>>吗?`,
@@ -1599,16 +983,16 @@
          }
        })
        let refreshtype = element.type + 'loading'
        // 删除按钮元素
        let _delActions = _this.state.delActions
        if (element.type === 'action') {
          _delActions.push(element)
        }
        _this.setState({
          config: _config,
          delActions: [..._this.state.delActions, element.card.uuid],
          [refreshtype]: true
        }, () => {
          _this.setState({
            [refreshtype]: false
          })
          delActions: _delActions,
          thawButtons: thawButtons.filter(key => key !== element.card.uuid)
        })
      },
      onCancel() {}
@@ -1626,100 +1010,175 @@
  }
  /**
   * @description 按钮双击触发子配置
   */
  btnDoubleClick = (element) => {
    if (!element.origin && (element.OpenType === 'pop' || element.OpenType === 'popview' || element.OpenType === 'blank' || element.OpenType === 'tab')) {
      this.setSubConfig(element)
    } else {
      notification.warning({
        top: 92,
        message: '此按钮无子配置项!',
        duration: 10
      })
    }
  }
  /**
   * @description 验证信息保存
   */
  verifySubmit = () => {
    const { card } = this.state
    let config = JSON.parse(JSON.stringify(this.state.config))
    let _verify = this.verifyRef.state.verify
    if (card.OpenType === 'excelIn') {
      this.verifyRef.handleConfirm().then(res => {
        config.action = config.action.map(item => {
          if (item.uuid === card.uuid) {
            item.verify = res
          }
          return item
        })
        this.setState({
          profileVisible: false,
          config: config,
          card: ''
        })
      })
    } else if (card.execMode) {
      this.verifyRef.handleConfirm().then(res => {
        config.action = config.action.map(item => {
          if (item.uuid === card.uuid) {
            item.verify = res
          }
          return item
        })
        this.setState({
          profileVisible: false,
          config: config,
          card: '',
        })
      })
    } else {
      let _verify = this.verifyRef.state.verify
    config.action = config.action.map(item => {
      if (item.uuid === card.uuid) {
        item.verify = _verify
      if (card.OpenType !== 'excelOut' && _verify.default === 'false' && _verify.scripts.length === 0) {
        notification.warning({
          top: 92,
          message: '不执行默认sql时,必须设置自定义脚本!',
          duration: 10
        })
        return
      } else if (card.OpenType === 'excelOut') {
        let _cols = _verify.columns.map(col => col.Column)
        let _vcols = Array.from(new Set(_cols))
        if (_cols.length > _vcols.length) {
          notification.warning({
            top: 92,
            message: 'Excel列字段名,不可重复!',
            duration: 10
          })
          return
        }
      }
      return item
    })
    this.setState({
      profileVisible: false,
      config: config,
      card: '',
      actionloading: true
    }, () => {
      this.setState({
        actionloading: false
      config.action = config.action.map(item => {
        if (item.uuid === card.uuid) {
          item.verify = _verify
        }
        return item
      })
    })
      this.setState({
        profileVisible: false,
        config: config,
        card: ''
      })
    }
  }
  // changeTemplate = () => {
  //   this.props.handleConfig('template')
  // }
  /**
   * @description 标签页保存
   */
  submitConfig = () => {
    const { delActions, thawButtons, originConfig } = this.state
    let config = JSON.parse(JSON.stringify(this.state.config))
    this.menuformRef.handleConfirm().then(res => {
      if (config.search[0] && config.search[0].origin) {
        config.search = config.search.filter(item => !item.origin)
      }
      if (config.action[0] && config.action[0].origin) {
        config.action = config.action.filter(item => !item.origin)
      }
      if (config.columns[0] && config.columns[0].origin) {
        config.columns = config.columns.filter(item => !item.origin)
      if (originConfig.isAdd) {
        if (config.search[0] && config.search[0].origin) {
          config.search = config.search.filter(item => !item.origin)
        }
        if (config.action[0] && config.action[0].origin) {
          config.action = config.action.filter(item => !item.origin)
        }
        if (config.columns[0] && config.columns[0].origin) {
          config.columns = config.columns.filter(item => !item.origin)
        }
      }
      let _LongParam = ''
      let _config = {...config, tables: this.state.selectedTables, ...res}
      // 保存时删除配置类型,system 、user
      delete _config.type
      try {
        _LongParam = window.btoa(window.encodeURIComponent(JSON.stringify(_config)))
      } catch (e) {
        notification.warning({
          top: 92,
          message: '编译错误',
          duration: 10
        })
        return
      // 未设置数据源或主键时,启用状态为false
      if (_config.setting.interType === 'inner' && !_config.setting.innerFunc && !_config.setting.dataresource) {
        _config.enabled = false
      } else if (!_config.setting.primaryKey) {
        _config.enabled = false
      }
      let btnParam = {
        func: 'sPC_Button_AddUpt',
        ParentID: _config.uuid,
        MenuNo: res.tabNo,
        Template: 'SubTable',
        PageParam: '',
        LongParam: '',
        LText: config.action.map((item, index) => {
          return `select '${item.uuid}' as menuid, '${item.label}' as menuname, '${(index + 1) * 10}' as Sort`
        })
      }
      _config.funcs = []
      btnParam.LText = btnParam.LText.join(' union all ')
      btnParam.LText = Utils.formatOptions(btnParam.LText)
      btnParam.timestamp = moment().format('YYYY-MM-DD HH:mm:ss') + '.000'
      btnParam.secretkey = Utils.encrypt(btnParam.LText, btnParam.timestamp)
      _config.funcs.push({
        type: 'view',
        subtype: 'view',
        uuid: _config.uuid,
        intertype: _config.setting.interType || 'inner',
        interface: _config.setting.interface || '',
        tableName: _config.setting.tableName || '',
        innerFunc: _config.setting.innerFunc || '',
        outerFunc: _config.setting.outerFunc || ''
      })
      let param = {
        func: 'sPC_Tab_AddUpt',
        MenuID: _config.uuid,
        MenuNo: res.tabNo,
        Template: 'SubTable',
        MenuName: res.tabName,
        Remark: res.Remark,
        Sort: 0,
        PageParam: JSON.stringify({Template: 'SubTable'}),
        LongParam: _LongParam
      }
      _config.action.forEach(item => {
        let tablename = item.OpenType === 'excelIn' ? (item.sheet || '') : (item.sql || '')
        if (item.OpenType === 'excelOut' && item.intertype === 'inner' && !item.innerFunc) {
          tablename = _config.setting.tableName || ''
        }
        if (item.OpenType === 'popview') {
          _config.funcs.push({
            type: 'tab',
            subtype: 'btn',
            uuid: item.uuid,
            label: item.label,
            linkTab: item.linkTab
          })
        } else {
          _config.funcs.push({
            type: 'button',
            subtype: 'btn',
            uuid: item.uuid,
            label: item.label,
            tableName: tablename,
            intertype: item.intertype,
            interface: item.interface || '',
            innerFunc: item.innerFunc || '',
            outerFunc: item.outerFunc || '',
            callbackFunc: item.callbackFunc || ''
          })
        }
      })
      if (this.state.closeVisible) { // 显示关闭对话框时,模态框中保存按钮,显示保存中状态
        this.setState({
@@ -1731,39 +1190,242 @@
        })
      }
      Api.getSystemConfig(param).then(response => {
        if (response.status) {
          this.setState({
            config: _config,
            originConfig: _config,
            searchloading: true,
            actionloading: true,
            columnsloading: true
          }, () => {
            this.setState({
              searchloading: false,
              actionloading: false,
              columnsloading: false
            }, () => {
      new Promise(resolve => {
        let deffers = []
        _config.funcs.forEach(item => {
          if (item.type === 'tab') {
            let deffer = new Promise(resolve => {
              Api.getSystemConfig({
                func: 'sPC_Get_LongParam',
                MenuID: item.linkTab
              }).then(result => {
                if (result.status && result.LongParam) {
                  let _LongParam = ''
                  if (result.LongParam) {
                    try {
                      _LongParam = JSON.parse(window.decodeURIComponent(window.atob(result.LongParam)))
                    } catch (e) {
                      console.warn('Parse Failure')
                      _LongParam = ''
                    }
                  }
                  if (_LongParam) {
                    item.menuNo = _LongParam.tabNo
                    item.subfuncs = _LongParam.funcs || []
                  }
                }
                resolve()
              })
            })
            deffers.push(deffer)
          }
        })
        if (deffers.length === 0) {
          resolve()
        } else {
          Promise.all(deffers).then(() => {
            resolve()
          })
        }
      }).then(() => {
        // 保存时删除配置类型,system 、user
        delete _config.type
        delete _config.isAdd
        try {
          _LongParam = window.btoa(window.encodeURIComponent(JSON.stringify(_config)))
        } catch (e) {
          notification.warning({
            top: 92,
            message: '编译错误',
            duration: 10
          })
          this.setState({
            menucloseloading: false,
            menuloading: false
          })
          return
        }
        let btnParam = {
          func: 'sPC_Button_AddUpt',
          Type: 40,
          ParentID: _config.uuid,
          MenuNo: res.tabNo,
          Template: 'SubTable',
          PageParam: '',
          LongParam: '',
          LText: []
        }
        let btntabs = []
        config.action.forEach((item, index) => {
          if (item.OpenType === 'popview') {
            btntabs.push(`select '${item.uuid}' as MenuID ,'${item.linkTab}' as Tabid,'${item.label}' as TabName ,'${(index + 1) * 10}' as Sort`)
          }
          btnParam.LText.push(`select '${item.uuid}' as menuid, '${item.label}' as menuname, '${(index + 1) * 10}' as Sort`)
        })
        btnParam.LText = btnParam.LText.join(' union all ')
        btnParam.LText = Utils.formatOptions(btnParam.LText)
        btnParam.timestamp = moment().format('YYYY-MM-DD HH:mm:ss') + '.000'
        btnParam.secretkey = Utils.encrypt(btnParam.LText, btnParam.timestamp)
        let tabParam = { // 添加标签按钮tab页
          func: 'sPC_sMenusTab_AddUpt',
          MenuID: _config.uuid,
          LText: btntabs.join(' union all ')
        }
        tabParam.LText = Utils.formatOptions(tabParam.LText)
        tabParam.timestamp = moment().format('YYYY-MM-DD HH:mm:ss') + '.000'
        tabParam.secretkey = Utils.encrypt(tabParam.LText, tabParam.timestamp)
        let param = {
          func: 'sPC_Tab_AddUpt',
          MenuID: _config.uuid,
          MenuNo: res.tabNo,
          Template: 'SubTable',
          MenuName: res.tabName,
          Remark: res.Remark,
          Sort: 0,
          PageParam: JSON.stringify({Template: 'SubTable'}),
          LongParam: _LongParam
        }
        // 有按钮或标签删除时,先进行删除操作
        // 删除成功后,保存页面配置
        new Promise(resolve => {
          if (delActions.length > 0) {
            let deffers = delActions.map(item => {
              let _param = {
                func: 'sPC_MainMenu_Del',
                MenuID: item.card.uuid
              }
              let _ParentParam = null
              try {
                _ParentParam = window.btoa(window.encodeURIComponent(JSON.stringify(item.card)))
              } catch (e) {
                console.warn('Stringify Failure')
                _ParentParam = null
              }
              if (_ParentParam) { // 删除按钮时,保存按钮配置信息,用于恢复按钮
                _param.ParentParam = _ParentParam
              }
              return new Promise(resolve => {
                Api.getSystemConfig(_param).then(response => {
                  resolve(response)
                })
              })
            })
            Promise.all(deffers).then(result => {
              let error = null
              result.forEach(response => {
                if (!response.status) {
                  error = response
                }
              })
              if (error) {
                this.setState({
                  menuloading: false,
                  menucloseloading: false
                })
                notification.warning({
                  top: 92,
                  message: error.message,
                  duration: 10
                })
                resolve(false)
              } else {
                this.setState({
                  delActions: []
                })
                resolve(true)
              }
            })
          } else if (delActions.length === 0) {
            resolve(true)
          }
        }).then(resp => {
          if (resp === false) return
          if (thawButtons.length > 0) {
            let defers = thawButtons.map(item => {
              return new Promise((resolve) => {
                Api.getSystemConfig({
                  func: 'sPC_MainMenu_ReDel',
                  MenuID: item
                }).then(res => {
                  if (res.status) {
                    resolve('')
                  } else {
                    resolve(res.message)
                  }
                })
              })
            })
            return Promise.all(defers)
          } else {
            return true
          }
        }).then(res => {
          if (res === true || res === false) return res
          let msg = res.filter(Boolean)[0]
          if (msg) {
            notification.warning({
              top: 92,
              message: msg,
              duration: 10
            })
            return false
          } else {
            this.setState({
              thawButtons: []
            })
            return true
          }
        }).then(resp => {
          if (resp === false) return
          Api.getSystemConfig(param).then(response => {
            if (response.status) {
              this.setState({
                config: _config,
                originConfig: _config
              }, () => {
                this.setState({
                  menuloading: false,
                  menucloseloading: false
                })
                this.submitAction(btnParam, tabParam)
              })
            } else {
              this.setState({
                menuloading: false,
                menucloseloading: false
              })
            })
            this.submitAction(btnParam)
              notification.warning({
                top: 92,
                message: response.message,
                duration: 10
              })
            }
          })
        } else {
          this.setState({
            menuloading: false,
            menucloseloading: false
          })
          notification.warning({
            top: 92,
            message: response.message,
            duration: 10
          })
        }
        })
      })
    }, () => {
      notification.warning({
@@ -1777,22 +1439,38 @@
  /**
   * @description 保存或修改菜单按钮
   */
  submitAction = (param) => {
  submitAction = (btnParam, tabParam) => {
    const { config } = this.state
    new Promise(resolve => {
      // 内部请求
      if (this.state.delActions.length > 0) {
        let deffers = this.state.delActions.map(item => {
          let _param = {
            func: 'sPC_MainMenu_Del',
            MenuID: item
          }
          return new Promise(resolve => {
            Api.getSystemConfig(_param).then(res => {
              resolve(res)
            })
      let deffers = []
      if (tabParam.LText) {
        let defer = new Promise(resolve => {
          Api.getSystemConfig(tabParam).then(result => {
            resolve(result)
          })
        })
        deffers.push(defer)
      }
      if (btnParam.LText) {
        let defer = new Promise(resolve => {
          Api.getSystemConfig(btnParam).then(result => {
            if (result.status) {
              this.setState({ // 保存成功后清空复制列表
                copyActions: []
              })
            }
            resolve(result)
          })
        })
        deffers.push(defer)
      }
      if (deffers.length === 0) {
        resolve(true)
      } else {
        Promise.all(deffers).then(result => {
          let error = false
          result.forEach(res => {
@@ -1809,35 +1487,9 @@
            })
            resolve(false)
          } else {
            this.setState({
              delActions: []
            })
            resolve(param)
            resolve(true)
          }
        })
      } else if (this.state.delActions.length === 0) {
        resolve(param)
      }
    }).then(res => {
      if (res === false) return res
      if (res.LText) {
        return Api.getSystemConfig(res)
      } else {
        return 'copy'
      }
    }).then(response => {
      if (response === false || response === 'copy') return response
      if (response.status) {
        return 'copy'
      } else {
        notification.warning({
          top: 92,
          message: response.message,
          duration: 10
        })
        return false
      }
    }).then(response => {
      if (response === false) return response
@@ -1865,10 +1517,10 @@
            let _LongParam = ''
  
            if (result.LongParam) {
              _LongParam = window.decodeURIComponent(window.atob(result.LongParam))
              try {
                _LongParam = JSON.parse(_LongParam)
                _LongParam = JSON.parse(window.decodeURIComponent(window.atob(result.LongParam)))
              } catch (e) {
                console.warn('Parse Failure')
                _LongParam = ''
              }
            }
@@ -1898,8 +1550,7 @@
          duration: 2
        })
        if (this.state.closeVisible) {
          let view = this.props.menu ? this.props.menu.type : ''
          this.props.handleConfig(view)
          this.handleViewBack()
        } else {
          this.setState({
            menuloading: false,
@@ -1919,24 +1570,14 @@
    const { config, originConfig } = this.state
    let _this = this
    let isAdd = false
    if (
      (config.search[0] && config.search[0].origin) ||
      (config.action[0] && config.action[0].origin) ||
      (config.columns[0] && config.columns[0].origin)
    ) {
      isAdd = true
    }
    if (isAdd) {
    if (originConfig.isAdd) {
      confirm({
        content: '菜单尚未提交,确定放弃保存吗?',
        okText: this.state.dict['header.confirm'],
        cancelText: this.state.dict['header.cancel'],
        onOk() {
          let view = _this.props.menu ? _this.props.menu.type : ''
          _this.props.handleConfig(view)
          _this.handleViewBack()
        },
        onCancel() {}
      })
@@ -1949,8 +1590,7 @@
            closeVisible: true
          })
        } else {
          let view = this.props.menu ? this.props.menu.type : ''
          this.props.handleConfig(view)
          this.handleViewBack()
        }
      }, () => {
        this.setState({
@@ -2145,17 +1785,13 @@
    }
    this.setState({
      [addType + 'loading']: true,
      config: {...config, [addType]: items}
    }, () => {
      notification.success({
        top: 92,
        message: '操作成功',
        duration: 2
      })
      this.setState({
        [addType + 'loading']: false
      })
    })
    notification.success({
      top: 92,
      message: '操作成功',
      duration: 2
    })
  }
@@ -2236,7 +1872,7 @@
      if (
        res.interType === 'inner' &&
        !res.innerFunc &&
        res.dataresource.length > 50 &&
        /[^\s]+\s+[^\s]+/ig.test(res.dataresource) &&
        config.setting.dataresource !== res.dataresource
      ) {
        let param = {
@@ -2255,11 +1891,6 @@
      this.setState({
        config: {...config, setting: res},
        settingVisible: false,
        columnsloading: true
      }, () => {
        this.setState({
          columnsloading: false
        })
      })
    })
  }
@@ -2268,19 +1899,10 @@
   * @description 设置可配置按钮
   */
  setSubConfig = (btn) => {
    const { config, originConfig } = this.state
    const {menu, editTab, tabConfig, editSubTab, btnTab, btnTabConfig} = this.props
    const { config, originConfig, activeKey } = this.state
    let isAdd = false
    if (
      (config.search[0] && config.search[0].origin) ||
      (config.action[0] && config.action[0].origin) ||
      (config.columns[0] && config.columns[0].origin)
    ) {
      isAdd = true
    }
    if (isAdd) {
    if (originConfig.isAdd) {
      notification.warning({
        top: 92,
        message: '菜单尚未保存,请保存菜单配置!',
@@ -2300,9 +1922,41 @@
          this.setState({
            loading: true
          })
          // 子菜单信息验证通过后,跳转子按钮配置页面
          let _view = ''
          let _subtab = editSubTab
          if (btn.OpenType === 'pop') {
            _view = 'Modal'             // 表单页面
          } else if (btn.OpenType === 'popview') {
            _view = btn.tabType        // 新弹窗标签模板
            _subtab = btn
          }
          if (editSubTab) {
            editSubTab.activeKey = activeKey
          } else {
            editTab.activeKey = activeKey
          }
          let param = {
            editMenu: menu,
            optionLibs: this.state.optionLibs,
            editTab: editTab,
            tabConfig: editSubTab ? tabConfig : originConfig,
            editSubTab: _subtab,
            subTabConfig: editSubTab ? originConfig : null,
            btnTab: btnTab,
            btnTabConfig: btnTabConfig,
            editAction: btn,
            subConfig: '',
            tabview: _view
          }
          Api.getSystemConfig({
            func: 'sPC_Get_LongParam',
            MenuID: btn.uuid
            MenuID: btn.OpenType === 'popview' ? btn.linkTab : btn.uuid
          }).then(res => {
            if (res.status) {
              this.setState({
@@ -2310,14 +1964,21 @@
              })
              let _LongParam = ''
              if (res.LongParam) {
                _LongParam = window.decodeURIComponent(window.atob(res.LongParam))
                try {
                  _LongParam = JSON.parse(_LongParam)
                  _LongParam = JSON.parse(window.decodeURIComponent(window.atob(res.LongParam)))
                } catch (e) {
                  console.warn('Parse Failure')
                  _LongParam = ''
                }
              }
              this.props.handleSubConfig(btn, config, _LongParam, 'tabButton')
              if (_LongParam && param.tabview === 'Modal' && _LongParam.type === 'Modal') {
                param.subConfig = _LongParam
              } else if (_LongParam && param.tabview === 'SubTable' && _LongParam.Template === 'SubTable') {
                param.subConfig = _LongParam
              }
              this.props.handleView(param)
            } else {
              this.setState({
                loading: false
@@ -2346,7 +2007,13 @@
    if (config.setting.interType === 'inner' && !config.setting.innerFunc && !config.setting.dataresource) {
      notification.warning({
        top: 92,
        message: '菜单尚未设置数据源,不可启用!',
        message: '尚未设置数据源,不可启用!',
        duration: 10
      })
    } else if (!config.setting.primaryKey) {
      notification.warning({
        top: 92,
        message: '尚未设置主键,不可启用!',
        duration: 10
      })
    } else {
@@ -2357,31 +2024,221 @@
  }
  onColumnNameChange = () => {
    const { showColumnName } = this.state
    const { showColumnName, config } = this.state
    if (!showColumnName) {
      let fields = []
      config.columns.forEach(col => {
        if (col.field) {
          fields.push(col.field)
        }
      })
      fields = fields.join(',')
      let textArea = document.createElement('textarea')
      textArea.value = fields
      document.body.appendChild(textArea)
      textArea.select()
      try {
        document.execCommand('copy')
        document.body.removeChild(textArea)
      } catch (err) {
        document.body.removeChild(textArea)
      }
    }
    this.setState({
      showColumnName: !showColumnName
    })
  }
  dontsave = () => {
    let view = this.props.menu ? this.props.menu.type : ''
    this.props.handleConfig(view)
  /**
   * @description 解冻按钮
   */
  handleThaw = () => {
    const { config } = this.state
    this.setState({
      thawBtnVisible: true
    })
    Api.getSystemConfig({
      func: 'sPC_Get_FrozenMenu',
      ParentID: config.uuid,
      TYPE: 40
    }).then(res => {
      if (res.status) {
        let _list = []
        res.data.forEach(menu => {
          let _conf = ''
          if (menu.ParentParam) {
            try {
              _conf = JSON.parse(window.decodeURIComponent(window.atob(menu.ParentParam)))
            } catch (e) {
              console.warn('Parse Failure')
              _conf = ''
            }
          }
          if (_conf) {
            _list.push({
              key: menu.MenuID,
              title: menu.MenuName,
              btnParam: _conf
            })
          }
        })
        this.setState({
          thawbtnlist: _list
        })
      } else {
        notification.warning({
          top: 92,
          message: res.message,
          duration: 10
        })
      }
    })
  }
  /**
   * @description 解冻按钮提交
   */
  thawBtnSubmit = () => {
    const { thawButtons, config, thawbtnlist } = this.state
    // 三级菜单解除冻结
    if (this.refs.trawmenu.state.targetKeys.length === 0) {
      notification.warning({
        top: 92,
        message: this.state.dict['form.required.select'] + this.state.dict['header.form.thawbutton'],
        duration: 10
      })
    } else {
      thawbtnlist.forEach(item => {
        if (this.refs.trawmenu.state.targetKeys.includes(item.key)) {
          config.action.push(item.btnParam)
        }
      })
      this.setState({
        thawButtons: [...thawButtons, ...this.refs.trawmenu.state.targetKeys],
        config: config,
        thawBtnVisible: false
      })
    }
  }
  /**
   * @description 创建按钮接口(写入)
   */
  btnCreatInterface = () => {
    const { config } = this.state
    this.menuformRef.handleConfirm().then(res => {
      this.actionFormRef.handleConfirm().then(result => {
        if (!['pop', 'exec', 'prompt'].includes(result) || result.funcType || result.intertype !== 'inner' || result.innerFunc ) {
          notification.warning({
            top: 92,
            message: '打开方式为 弹窗(表单)、提示框或直接执行,且使用系统函数时,才可以创建接口!',
            duration: 10
          })
          return
        }
        let _menu = {
          type: 'subtable',
          MenuID: config.uuid,
          menuName: res.tabName,
          menuNo: res.tabNo
        }
        this.refs.btnCreatInterface.triggerInInterface(result, config, _menu)
      })
    })
  }
  /**
   * @description 创建表格接口
   */
  tableCreatInterface = () => {
    const { config } = this.state
    this.menuformRef.handleConfirm().then(res => {
      this.settingRef.handleConfirm().then(setting => {
        if (setting.interType !== 'inner' || setting.innerFunc) {
          notification.warning({
            top: 92,
            message: '接口类型为-内部,且不存在内部函数时,才可以创建接口!',
            duration: 10
          })
          return
        }
        let _config = {...config, setting: setting}
        let _menu = {
          type: 'subtable',
          MenuID: config.uuid,
          menuName: res.tabName,
          menuNo: res.tabNo
        }
        this.refs.tableCreatInterface.triggerOutInterface(_menu, _config)
      })
    })
  }
  pasteSubmit = () => {
    this.pasteFormRef.handleConfirm().then(res => {
      if (res.copyType !== 'action') {
        notification.warning({
          top: 92,
          message: '配置信息格式错误!',
          duration: 10
        })
        return
      } else if (!['pop', 'prompt', 'exec', 'excelIn', 'excelOut', 'popview'].includes(res.OpenType)) {
        notification.warning({
          top: 92,
          message: '不支持此打开方式!',
          duration: 10
        })
        return
      }
      this.setState({
        modaltype: ''
      }, () => {
        this.handleAction(res, 'copy')
      })
    })
  }
  render () {
    const configAction = this.state.config.action.filter(_action =>
    const { modaltype, activeKey, config } = this.state
    const configAction = config.action.filter(_action =>
      !_action.origin && (_action.OpenType === 'pop' || _action.OpenType === 'popview' || _action.OpenType === 'blank' || _action.OpenType === 'tab')
    )
    let hasbtncrtinter = false
    if (modaltype === 'actionEdit' && config.setting.interType === 'inner' && !config.setting.innerFunc && config.setting.dataresource) {
      hasbtncrtinter = true
    }
    return (
      <div className="common-table-board">
        <DndProvider backend={HTML5Backend}>
          {/* 工具栏 */}
          <div className="tools">
            <Collapse accordion defaultActiveKey="0" bordered={false}>
            <Collapse accordion defaultActiveKey={activeKey} bordered={false} onChange={(key) => this.setState({activeKey: key})}>
              {/* 基本信息 */}
              <Panel header={'标签基本信息'} key="0" id="common-basedata">
              <Panel forceRender={true} header={'标签基本信息'} key="0" id="common-basedata">
                {/* 菜单信息 */}
                <MenuForm
                  dict={this.state.dict}
@@ -2442,14 +2299,19 @@
                    return (<SourceElement key={index} content={item}/>)
                  })}
                </div>
                {configAction.length > 0 ?
                  <p className="config-btn-title">
                    <Tooltip placement="topLeft" title="点击按钮,可完成或查看按钮配置信息。">
                      <Icon type="question-circle" />
                    </Tooltip>
                    {this.state.dict['header.menu.action.configurable']}
                  </p> : null
                }
                <div className="config-btn">
                  {configAction.length > 0 ?
                    <p className="config-btn-title">
                      <Tooltip placement="topLeft" title="点击按钮,可完成或查看按钮配置信息。">
                        <Icon type="question-circle" />
                      </Tooltip>
                      {this.state.dict['header.menu.action.configurable']}
                    </p> : null
                  }
                  <div className="thawbutton" title={this.state.dict['header.form.thawbutton']} onClick={this.handleThaw}>
                    <Icon type="unlock" />
                  </div>
                </div>
                {configAction.map((item, index) => {
                  return (
                    <div key={index}>
@@ -2475,10 +2337,14 @@
            </Collapse>
          </div>
          <div className="setting">
            <Card title={'标签(子表)页面配置'} bordered={false} extra={
            <Card title={
              <div>
                标签(子表)页面配置
                <Icon type="redo" style={{marginLeft: '10px'}} title="刷新标签列表" onClick={this.reloadTab} />
              </div>
            } bordered={false} extra={
              <div>
                <Switch className="big" checkedChildren="启" unCheckedChildren="停" checked={this.state.config.enabled} onChange={this.onEnabledChange} />
                {/* <Button type="primary" onClick={this.changeTemplate}>{this.state.dict['header.menu.template.change']}</Button> */}
                <Button type="primary" onClick={this.submitConfig} loading={this.state.menuloading}>{this.state.dict['header.save']}</Button>
                <Button onClick={this.cancelConfig}>{this.state.dict['header.return']}</Button>
              </div>
@@ -2488,111 +2354,153 @@
                <Tooltip placement="bottomLeft" overlayClassName="middle" title="在左侧工具栏《搜索》中,选择对应搜索框拖至此处添加;或点击按钮《添加搜索条件》批量添加,选择批量添加时,需提前选择使用表。">
                  <Icon type="question-circle" />
                </Tooltip>
                {!this.state.searchloading ?
                  <DragElement
                    type="search"
                    list={this.state.config.search}
                    handleList={this.handleList}
                    handleMenu={this.handleSearch}
                    deleteMenu={this.deleteElement}
                    placeholder={this.state.dict['header.form.search.placeholder']}
                  /> : null
                }
                <DragElement
                  type="search"
                  list={this.state.config.search}
                  handleList={this.handleList}
                  handleMenu={this.handleSearch}
                  deleteMenu={this.deleteElement}
                  placeholder={this.state.dict['header.form.search.placeholder']}
                />
              </div>
              <div className="action-list">
                <Tooltip placement="bottomLeft" overlayClassName="middle" title="在左侧工具栏《按钮》中,选择对应类型的按钮拖至此处添加,如选择按钮类型为表单、新标签页等含有配置页面的按钮,可在左侧工具栏-按钮-可配置按钮处,点击按钮完成相关配置。注:当设置按钮显示位置为表格时,显示列会增加操作列。">
                  <Icon type="question-circle" />
                </Tooltip>
                {!this.state.actionloading ?
                  <DragElement
                    type="action"
                    list={this.state.config.action}
                    handleList={this.handleList}
                    handleMenu={this.handleAction}
                    copyElement={(val) => this.handleAction(val, 'copy')}
                    deleteMenu={this.deleteElement}
                    profileMenu={this.profileAction}
                    placeholder={this.state.dict['header.form.action.placeholder']}
                  /> : null
                }
                <div className="copybutton" title={this.state.dict['header.form.paste']} onClick={() => {this.setState({modaltype: 'paste'})}}>
                  <Icon type="snippets" />
                </div>
                <DragElement
                  type="action"
                  list={this.state.config.action}
                  setting={this.state.config.setting}
                  handleList={this.handleList}
                  handleMenu={this.handleAction}
                  copyElement={(val) => this.handleAction(val, 'copy')}
                  deleteMenu={this.deleteElement}
                  profileMenu={this.profileAction}
                  doubleClickCard={this.btnDoubleClick}
                  placeholder={this.state.dict['header.form.action.placeholder']}
                />
              </div>
              <div className="column-list">
                <Tooltip placement="bottomLeft" overlayClassName="middle" title="在左侧工具栏《显示列》中,选择对应类型的显示列拖至此处添加;或点击《添加显示列》按钮批量添加,选择批量添加时,需提前选择使用表。注:添加合并列时,需设置可选列。">
                  <Icon type="question-circle" />
                </Tooltip>
                <Switch checkedChildren="开" unCheckedChildren="关" defaultChecked={this.state.showColumnName} onChange={this.onColumnNameChange} />
                {!this.state.columnsloading ?
                  <DragElement
                    type="columns"
                    list={this.state.config.columns}
                    setting={this.state.config.setting}
                    gridBtn={this.state.config.gridBtn}
                    handleList={this.handleList}
                    handleMenu={this.handleColumn}
                    deleteMenu={this.deleteElement}
                    handleGridBtn={this.handleGridBtn}
                    showfield={this.state.showColumnName}
                    placeholder={this.state.dict['header.form.column.placeholder']}
                  /> : null
                }
                <DragElement
                  type="columns"
                  list={this.state.config.columns}
                  setting={this.state.config.setting}
                  gridBtn={this.state.config.gridBtn}
                  handleList={this.handleList}
                  handleMenu={this.handleColumn}
                  deleteMenu={this.deleteElement}
                  handleGridBtn={this.handleGridBtn}
                  showfield={this.state.showColumnName}
                  placeholder={this.state.dict['header.form.column.placeholder']}
                />
              </div>
            </Card>
          </div>
        </DndProvider>
        {/* 编辑搜索条件、按钮、显示列 */}
        {/* 编辑搜索条件 */}
        <Modal
          title={this.state.modalTitle}
          visible={this.state.visible}
          title={this.state.dict['header.modal.search.edit']}
          visible={modaltype === 'search'}
          width={700}
          onCancel={() => { this.setState({ visible: false }) }}
          maskClosable={false}
          onOk={this.handleSubmit}
          onCancel={this.editModalCancel}
          destroyOnClose
        >
          <SearchForm
            dict={this.state.dict}
            card={this.state.card}
            formlist={this.state.formlist}
            inputSubmit={this.handleSubmit}
            optionLibs={this.state.optionLibs}
            wrappedComponentRef={(inst) => this.searchFormRef = inst}
          />
        </Modal>
        {/* 编辑按钮:复制、编辑 */}
        <Modal
          title={modaltype === 'actionEdit' ? this.state.dict['header.modal.action.edit'] : this.state.dict['header.modal.action.copy']}
          visible={modaltype === 'actionEdit' || modaltype === 'actionCopy'}
          width={700}
          maskClosable={false}
          onCancel={this.editModalCancel}
          footer={[
            this.state.formtemp === 'action' ?
            <Button key="delete" className="mk-btn mk-purple" onClick={this.creatFunc} loading={this.state.funcLoading}>{this.state.dict['header.menu.func.create']}</Button> : null,
            <Button key="cancel" onClick={() => { this.setState({ visible: false }) }}>{this.state.dict['header.cancel']}</Button>,
            hasbtncrtinter ? <CreateInterface key="interface" dict={this.state.dict} ref="btnCreatInterface" trigger={this.btnCreatInterface}/> : null,
            modaltype === 'actionEdit' ? <CreateFunc key="create" dict={this.state.dict} ref="btnCreatFunc" trigger={this.creatFunc}/> : null,
            <Button key="cancel" onClick={this.editModalCancel}>{this.state.dict['header.cancel']}</Button>,
            <Button key="confirm" type="primary" onClick={this.handleSubmit}>{this.state.dict['header.confirm']}</Button>
          ]}
          destroyOnClose
        >
          {this.state.formtemp === 'search' ?
            <SearchForm
              dict={this.state.dict}
              formlist={this.state.formlist}
              card={this.state.card}
              wrappedComponentRef={(inst) => this.formRef = inst}
            /> : null
          }
          {this.state.formtemp === 'action' ?
            <ActionForm
              dict={this.state.dict}
              card={this.state.card}
              tabs={this.state.tabviews}
              formlist={this.state.formlist}
              wrappedComponentRef={(inst) => this.formRef = inst}
            /> : null
          }
          {this.state.formtemp === 'columns' && this.state.card.type !== 'colspan' ?
            <ColumnForm
              dict={this.state.dict}
              card={this.state.card}
              formlist={this.state.formlist}
              wrappedComponentRef={(inst) => this.formRef = inst}
            /> : null
          }
          {this.state.formtemp === 'columns' && this.state.card.type === 'colspan' ?
            <ColspanForm
              dict={this.state.dict}
              card={this.state.card}
              columns={this.state.config.columns}
              wrappedComponentRef={(inst) => this.formRef = inst}
            /> : null
          }
          {this.state.formtemp === 'gridbtn' ?
            <GridBtnForm
              dict={this.state.dict}
              card={this.state.config.gridBtn}
              wrappedComponentRef={(inst) => this.formRef = inst}
            /> : null
          }
          <ActionForm
            dict={this.state.dict}
            card={this.state.card}
            tabs={this.state.tabviews}
            formlist={this.state.formlist}
            inputSubmit={this.handleSubmit}
            setting={this.state.config.setting}
            wrappedComponentRef={(inst) => this.actionFormRef = inst}
          />
        </Modal>
        {/* 显示列编辑 */}
        <Modal
          title={this.state.dict['header.modal.column.edit']}
          visible={modaltype === 'columns'}
          width={700}
          maskClosable={false}
          onOk={this.handleSubmit}
          onCancel={this.editModalCancel}
          destroyOnClose
        >
          <ColumnForm
            dict={this.state.dict}
            card={this.state.card}
            MenuID={this.props.menu.MenuID}
            inputSubmit={this.handleSubmit}
            formlist={this.state.formlist}
            wrappedComponentRef={(inst) => this.columnFormRef = inst}
          />
        </Modal>
        {/* 合并列编辑 */}
        <Modal
          title={this.state.dict['header.modal.colspan.edit']}
          visible={modaltype === 'colspan'}
          width={700}
          maskClosable={false}
          onOk={this.handleSubmit}
          onCancel={this.editModalCancel}
          destroyOnClose
        >
          <ColspanForm
            dict={this.state.dict}
            card={this.state.card}
            inputSubmit={this.handleSubmit}
            columns={this.state.config.columns}
            wrappedComponentRef={(inst) => this.columnFormRef = inst}
          />
        </Modal>
        {/* 操作列编辑 */}
        <Modal
          title={this.state.dict['header.modal.gridbtn.edit']}
          visible={modaltype === 'gridbtn'}
          width={700}
          maskClosable={false}
          onOk={this.handleSubmit}
          onCancel={this.editModalCancel}
          destroyOnClose
        >
          <GridBtnForm
            dict={this.state.dict}
            inputSubmit={this.handleSubmit}
            card={this.state.config.gridBtn}
            wrappedComponentRef={(inst) => this.gridBtnFormRef = inst}
          />
        </Modal>
        {/* 根据字段名添加显示列及搜索条件 */}
        <Modal
@@ -2600,6 +2508,7 @@
          title={this.state.dict['header.edit']}
          visible={this.state.tableVisible}
          width={'65vw'}
          maskClosable={false}
          style={{minWidth: '900px', maxWidth: '1200px'}}
          cancelText={this.state.dict['header.close']}
          onOk={this.addFieldSubmit}
@@ -2624,26 +2533,51 @@
          title={'验证信息'}
          visible={this.state.profileVisible}
          width={'75vw'}
          maskClosable={false}
          style={{minWidth: '900px', maxWidth: '1200px'}}
          onOk={this.verifySubmit}
          onCancel={() => { this.setState({ profileVisible: false }) }}
          destroyOnClose
        >
          <VerifyCard card={this.state.card} columns={this.state.config.columns} wrappedComponentRef={(inst) => this.verifyRef = inst} dict={this.state.dict} />
          {this.state.card && this.state.card.OpenType !== 'excelIn' ?
            <VerifyCard
              floor="subtable"
              card={this.state.card}
              dict={this.state.dict}
              columns={this.state.config.columns}
              wrappedComponentRef={(inst) => this.verifyRef = inst}
            /> : null
          }
          {this.state.card && this.state.card.OpenType === 'excelIn' ?
            <VerifyCardExcelIn
              card={this.state.card}
              dict={this.state.dict}
              columns={this.state.config.columns}
              wrappedComponentRef={(inst) => this.verifyRef = inst}
            /> : null
          }
          {this.state.card && this.state.card.OpenType === 'excelOut' ?
            <VerifyCardExcelOut
              card={this.state.card}
              dict={this.state.dict}
              wrappedComponentRef={(inst) => this.verifyRef = inst}
            /> : null
          }
        </Modal>
        {/* 设置全局配置及列表数据源 */}
        <Modal
          title={this.state.dict['header.edit']}
          visible={this.state.settingVisible}
          width={700}
          // onOk={this.settingSave}
          maskClosable={false}
          onCancel={() => { // 取消修改
            this.setState({
              settingVisible: false
            })
          }}
          footer={[
            <Button key="delete" className="mk-btn mk-purple" onClick={this.tableCreatFunc} loading={this.state.funcLoading}>{this.state.dict['header.menu.func.create']}</Button>,
            <CreateInterface key="interface" dict={this.state.dict} ref="tableCreatInterface" trigger={this.tableCreatInterface}/>,
            <CreateFunc key="create" dict={this.state.dict} ref="tableCreatFunc" trigger={this.tableCreatFunc}/>,
            <Button key="cancel" onClick={() => { this.setState({ settingVisible: false }) }}>{this.state.dict['header.cancel']}</Button>,
            <Button key="confirm" type="primary" onClick={this.settingSave}>{this.state.dict['header.confirm']}</Button>
          ]}
@@ -2652,6 +2586,7 @@
          <SettingForm
            dict={this.state.dict}
            tabId={this.state.config.uuid}
            inputSubmit={this.settingSave}
            data={this.state.config.setting}
            columns={this.state.config.columns}
            usefulFields={this.props.permFuncField}
@@ -2661,16 +2596,45 @@
        <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.menucloseloading} onClick={this.submitConfig}>{this.state.dict['header.save']}</Button>,
            <Button key="confirm" className="mk-btn mk-yellow" onClick={this.dontsave}>{this.state.dict['header.notsave']}</Button>,
            <Button key="confirm" className="mk-btn mk-yellow" onClick={this.handleViewBack}>{this.state.dict['header.notsave']}</Button>,
            <Button key="cancel" onClick={() => { this.setState({closeVisible: false}) }}>{this.state.dict['header.cancel']}</Button>
          ]}
          destroyOnClose
        >
          {this.state.dict['header.menu.config.placeholder']}
        </Modal>
        {/* 解冻按钮模态框 */}
        <Modal
          title={this.state.dict['header.form.thawbutton']}
          okText={this.state.dict['header.confirm']}
          cancelText={this.state.dict['header.cancel']}
          visible={this.state.thawBtnVisible}
          onOk={this.thawBtnSubmit}
          onCancel={() => {this.setState({thawBtnVisible: false, thawbtnlist: null})}}
          destroyOnClose
        >
          {!this.state.thawbtnlist && <Spin style={{marginLeft: 'calc(50% - 22px)', marginTop: '70px', marginBottom: '70px'}} size="large" />}
          {this.state.thawbtnlist && <TransferForm ref="trawmenu" menulist={this.state.thawbtnlist}/>}
        </Modal>
        {/* 按钮配置信息粘贴复制 */}
        <Modal
          title={this.state.dict['header.form.paste']}
          visible={modaltype === 'paste'}
          width={600}
          maskClosable={false}
          onOk={this.pasteSubmit}
          onCancel={() => {this.setState({modaltype: ''})}}
          destroyOnClose
        >
          <PasteForm
            dict={this.state.dict}
            wrappedComponentRef={(inst) => this.pasteFormRef = inst}
          />
        </Modal>
        {this.state.loading && <Spin size="large" />}
      </div>
@@ -2680,6 +2644,7 @@
const mapStateToProps = (state) => {
  return {
    sysRoles: state.sysRoles,
    permFuncField: state.permFuncField
  }
}