king
2023-05-25 5e871a4164869bac7927ea6884dbadd650b1cadf
Merge branch 'master' into positec
84个文件已修改
3个文件已添加
3512 ■■■■■ 已修改文件
public/options.json 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/index.js 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/mobimg/xflow.png 补丁 | 查看 | 原始文档 | blame | 历史
src/components/header/index.jsx 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/header/index.scss 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/index.js 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/card/balcony/options.jsx 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/card/cardcellcomponent/elementform/index.jsx 214 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/card/cardcellcomponent/formconfig.jsx 113 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/card/cardcellcomponent/index.jsx 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/card/data-card/options.jsx 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/card/double-data-card/options.jsx 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/carousel/data-card/options.jsx 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/module/voucher/voucherTable/index.scss 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/share/actioncomponent/actionform/index.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/share/actioncomponent/formconfig.jsx 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/share/actioncomponent/index.jsx 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/share/pastebasetable/index.jsx 35 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/share/pastecomponent/index.jsx 40 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/share/usercomponent/index.jsx 32 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/table/base-table/columns/editColumn/formconfig.jsx 67 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/table/base-table/columns/editColumn/index.jsx 160 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/table/base-table/columns/editColumn/index.scss 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/table/base-table/columns/index.jsx 66 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/table/base-table/columns/index.scss 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/table/base-table/index.jsx 42 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/table/edit-table/columns/editColumn/formconfig.jsx 79 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/table/edit-table/columns/editColumn/index.jsx 79 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/table/edit-table/columns/index.jsx 78 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/table/edit-table/columns/index.scss 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/table/edit-table/columns/tableIn/customscript/index.jsx 44 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/table/edit-table/columns/tableIn/index.jsx 34 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/table/edit-table/columns/tableIn/index.scss 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/table/edit-table/index.jsx 7 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/table/edit-table/options.jsx 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/table/normal-table/columns/editColumn/formconfig.jsx 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/table/normal-table/columns/editColumn/index.jsx 101 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/table/normal-table/columns/index.jsx 65 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/table/normal-table/columns/index.scss 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/table/normal-table/index.jsx 14 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/table/normal-table/options.jsx 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/timeline/normal-timeline/options.jsx 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/modulecell/index.jsx 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/modulesource/option.jsx 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/replaceField/index.jsx 14 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/transfer/index.jsx 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/basetable/index.jsx 80 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/card/cardcellList/index.jsx 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/module/voucher/index.jsx 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/module/voucher/voucherTable/index.scss 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/share/normalTable/index.jsx 19 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/table/edit-table/index.jsx 5 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/table/edit-table/normalTable/index.jsx 109 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/index.jsx 172 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/popview/index.jsx 149 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/actionList/normalbutton/index.jsx 54 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/actionList/printbutton/index.jsx 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/mutilform/index.jsx 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/settingcomponent/index.jsx 13 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/comtableconfig/updatetable/index.jsx 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/actioncomponent/verifyexcelin/customscript/index.jsx 53 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/actioncomponent/verifyexcelin/index.jsx 29 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/actioncomponent/verifyexcelin/index.scss 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/actioncomponent/verifyexcelout/customscript/index.jsx 5 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/actioncomponent/verifyexcelout/index.jsx 28 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/zshare/codemirror/index.scss 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/zshare/formconfig.jsx 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/zshare/modalform/index.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/zshare/verifycard/baseform/index.jsx 142 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/zshare/verifycard/baseform/index.scss 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/zshare/verifycard/billcodeform/index.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/zshare/verifycard/contrastform/index.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/zshare/verifycard/customform/index.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/zshare/verifycard/fullScripts/index.jsx 130 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/zshare/verifycard/fullScripts/index.scss 130 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/zshare/verifycard/index.jsx 121 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/zshare/verifycard/index.scss 130 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/zshare/verifycard/uniqueform/index.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/zshare/verifycard/voucherform/index.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/utils-custom.js 129 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/utils.js 37 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/billprint/index.jsx 14 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/menudesign/index.jsx 64 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mobdesign/index.jsx 93 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/pcdesign/index.jsx 89 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/tabledesign/index.jsx 101 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/tabledesign/source.jsx 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
public/options.json
@@ -8,8 +8,9 @@
  "filter": "false",
  "defaultApp": "",
  "defaultLang": "zh-CN",
  "WXAppID": "",
  "WXAppID": "wx4d8a34c8d4494872",
  "WXminiAppID": "",
  "WXNotice": "true",
  "nginx": "true",
  "debugger": true,
  "licenseKey": "",
src/api/index.js
@@ -98,17 +98,18 @@
  /**
   * @description 微信业务请求
   */
  wxAccessToken () {
  wxAccessToken (domain = '') {
    let _url = window.GLOB.baseurl + 'wxpay/getaccesstoken'
    if (process.env.NODE_ENV !== 'production') {
      _url = document.location.origin + '/wxpay/getaccesstoken'
    if (domain) {
      _url = domain + 'wxpay/getaccesstoken'
    }
    return new Promise(resolve => {
      if (window.GLOB.accessToken.accessTime && (parseInt(new Date().getTime() / 1000) - window.GLOB.accessToken.accessTime < 30)) {
      if (window.GLOB.accessToken.domain === domain && window.GLOB.accessToken.accessTime && (parseInt(new Date().getTime() / 1000) - window.GLOB.accessToken.accessTime < 30)) {
        resolve(window.GLOB.accessToken)
      } else {
        window.GLOB.accessToken = {}
        window.GLOB.accessToken = {domain}
        axios({
          url: _url,
          method: 'get'
@@ -128,7 +129,10 @@
   * @description 微信业务请求
   */
  wxNginxRequest (url, method, param) {
    let _url = window.GLOB.location + '/' + url
    let _url = url
    if (!/^http/.test(url)) {
      _url = window.GLOB.location + '/' + url
    if (process.env.NODE_ENV === 'production') {
      _url = document.location.origin + '/' + url
    }
@@ -141,6 +145,7 @@
      _url = window.GLOB.location + ':8443/' + url
      if (process.env.NODE_ENV === 'production') {
        _url = document.location.origin + ':8443/' + url
        }
      }
    }
    
@@ -1065,9 +1070,6 @@
   */
  getWxNativePay (param) {
    let _url = window.GLOB.baseurl + 'wxpay/wxNativePay'
    if (process.env.NODE_ENV !== 'production') {
      _url = document.location.origin + '/wxpay/wxNativePay'
    }
    return axios({
      url: _url,
src/assets/mobimg/xflow.png
src/components/header/index.jsx
@@ -23,6 +23,7 @@
const { confirm } = Modal
const { Search } = Input
const Resetpwd = asyncComponent(() => import('@/components/resetPassword'))
const QrCode = asyncComponent(() => import('@/components/qrcode'))
const LoginForm = asyncSpinComponent(() => import('./loginform'))
class Header extends Component {
@@ -534,6 +535,14 @@
    })
  }
  wxnotice = () => {
    Modal.success({
      className: 'mk-wx-notice',
      title: <QrCode card={{qrWidth: 320, color: '#000000'}} value={window.GLOB.baseurl + 'mob/wxnotice.html?userid=' + sessionStorage.getItem('UserID') + '&loginuid=' + sessionStorage.getItem('LoginUID')}/>,
      okText: '关闭'
    })
  }
  changeToHome = () => {
    if (!['linkage', 'menu_board'].includes(window.GLOB.navBar)) return
@@ -561,6 +570,9 @@
        <Menu.Item key="verup" onClick={this.verup}>
          页面更新
        </Menu.Item>
        {window.GLOB.WXNotice ? <Menu.Item key="wxnotice" onClick={this.wxnotice}>
          微信消息
        </Menu.Item> : null}
        {window.GLOB.appVersion ? <Menu.Item key="version" onClick={this.about}>
          关于
        </Menu.Item> : null}
src/components/header/index.scss
@@ -275,3 +275,18 @@
    }
  }
}
.mk-wx-notice {
  top: 100px!important;
  .anticon-check-circle {
    display: none;
  }
  .ant-modal-confirm-title {
    text-align: center;
    min-height: 320px;
  }
  .ant-modal-confirm-btns {
    float: none!important;
    text-align: center;
  }
}
src/index.js
@@ -74,6 +74,7 @@
    GLOB.nginx = config.nginx + '' === 'true'
    GLOB.WXAppID = config.WXAppID || ''
    GLOB.WXminiAppID = config.WXminiAppID || ''
    GLOB.WXNotice = config.WXNotice + '' === 'true'
    GLOB.accessToken = {}
    GLOB.mkHS = false
@@ -136,6 +137,7 @@
    if (options.sysType === 'cloud') { // cloud不可设置单点服务器地址,云端appkey为系统设置
      GLOB.appkey = options.cakey
      GLOB.WXNotice = false
    } else if (options.sysType === 'SSO') { // sso不可设置单点服务器地址
      GLOB.appkey = config.appkey
    } else if (options.sysType === 'local') { // 业务系统
src/menu/components/card/balcony/options.jsx
@@ -261,13 +261,13 @@
      type: 'radio',
      field: 'permission',
      label: '权限验证',
      initval: wrap.permission || 'false',
      initval: wrap.permission || (!appType ? 'true' : 'false'),
      required: false,
      options: [
        {value: 'true', label: '启用'},
        {value: 'false', label: '禁用'},
      ],
      forbid: !appType || sessionStorage.getItem('editMenuType') === 'popview'
      forbid: sessionStorage.getItem('editMenuType') === 'popview'
    },
    {
      type: 'select',
src/menu/components/card/cardcellcomponent/elementform/index.jsx
@@ -29,7 +29,7 @@
  color: ['eleType', 'datatype', 'width', 'lenWidRadio', 'noValue', 'copyable'],
}
class MainSearch extends Component {
class ElementEditForm extends Component {
  static propTpyes = {
    config: PropTypes.object,    // 组件信息
    formlist: PropTypes.any,     // 表单信息
@@ -38,28 +38,24 @@
  }
  state = {
    formlist: null,  // 表单信息
    eleType: '',
    datatype: '',
    showType: '',
    showInfo: 'false',
    fixStyle: '',
    link: ''
    formlist: null  // 表单信息
  }
  record = null
  UNSAFE_componentWillMount () {
    const { card, config, side } = this.props
    let _options = this.getOptions(card.eleType, card.datatype, card.link, (card.showType || 'line'), card.showInfo, card.fixStyle || '', card.posterType || '')
    const { card, config, side, formlist } = this.props
    this.record = {}
    formlist.forEach(item => {
      this.record[item.key] = item.initVal
    })
    let _options = this.getOptions()
    
    this.setState({
      link: card.link,
      eleType: card.eleType,
      datatype: card.datatype,
      showType: card.showType || 'line',
      showInfo: card.showInfo || 'false',
      fixStyle: card.fixStyle || '',
      posterType: card.posterType || '',
      formlist: this.props.formlist.map(item => {
      formlist: formlist.map(item => {
        item.hidden = !_options.includes(item.key)
        if (item.key === 'field' || item.key === 'linkurl' || item.key === 'bgImage' || item.key === 'posterField') {
@@ -154,50 +150,62 @@
    })
  }
  getOptions = (eleType, datatype, link, showType, showInfo, fixStyle, posterType) => {
    let _options = fromJS(cardTypeOptions[eleType]).toJS() // 选项列表
  getOptions = () => {
    let _options = fromJS(cardTypeOptions[this.record.eleType]).toJS() // 选项列表
    
    if (['text', 'number', 'picture', 'slider', 'barcode', 'qrcode', 'video', 'color'].includes(eleType)) {
      if (datatype === 'dynamic') {
    if (['text', 'number', 'picture', 'slider', 'barcode', 'qrcode', 'video', 'color'].includes(this.record.eleType)) {
      if (this.record.datatype === 'dynamic') {
        _options.push('field')
        if (eleType === 'number') {
        if (this.record.eleType === 'number') {
          _options.push('decimal', 'format')
        }
      } else if (eleType === 'picture' || eleType === 'video') {
      } else if (this.record.eleType === 'picture' || this.record.eleType === 'video') {
        _options.push('url')
      } else {
        _options.push('value')
      }
      if (eleType === 'video' && posterType) {
        if (posterType === 'dynamic') {
      if (this.record.eleType === 'video' && this.record.posterType) {
        if (this.record.posterType === 'dynamic') {
          _options.push('posterField')
        } else {
          _options.push('posterUrl')
        }
      }
      if (['text', 'picture'].includes(eleType) && link) {
        // if (link === 'dynamic' || link === 'static') {
          _options.push('linkurl', 'joint', 'linkType')
        // }
      } else if (eleType === 'picture' && !link) {
      if (['text', 'picture'].includes(this.record.eleType) && this.record.link) {
        _options.push('linkType')
        if (this.record.linkType === 'linkmenu') {
          _options.push('open', 'joint')
          if (this.record.link === 'static') {
            _options.push('linkmenu')
          } else {
            _options.push('linkurl')
          }
        } else if (this.record.linkType === 'other') {
          _options.push('linkurl', 'joint')
        } else {
          _options.push('linkurl')
        }
      } else if (this.record.eleType === 'picture' && !this.record.link) {
        _options.push('scale')
      } else if (eleType === 'slider') {
        if (showInfo === 'true') {
      } else if (this.record.eleType === 'slider') {
        if (this.record.showInfo === 'true') {
          _options.push('infoColor')
        }
        if (showType !== 'line') {
        if (this.record.showType !== 'line') {
          _options.push('outlineWidth', 'textAlign')
        }
      }
    } else if (eleType === 'icon') {
      if (datatype === 'dynamic') {
    } else if (this.record.eleType === 'icon') {
      if (this.record.datatype === 'dynamic') {
        _options.push('field', 'noValue')
      } else {
        _options.push('icon')
      }
    } else if (this.record.eleType === 'formula' && this.record.eval === 'true') {
      _options.push('decimal')
    }
    if (_options.includes('fixStyle') && fixStyle === 'alone') {
    if (_options.includes('fixStyle') && this.record.fixStyle === 'alone') {
      _options.push('fixSize', 'fixColor', 'fixLeft', 'fixRight')
    }
@@ -211,13 +219,22 @@
   * 3、切换标签类型,重置可选标签
   */
  selectChange = (key, value, option) => {
    const { card, config, side } = this.props
    const { datatype, eleType, showType, showInfo, fixStyle, posterType } = this.state
    const { config, side } = this.props
    this.record[key] = value
    if (key === 'eleType') {
      let _options = this.getOptions(value, datatype, '', showType, showInfo, fixStyle, posterType)
      this.record.link = ''
      let _options = this.getOptions()
      if (value === 'splitline') {
        this.record.color = '#EBE9E9'
      } else if (value === 'formula') {
        this.record.decimal = ''
      }
      
      let _formlist = this.state.formlist.map(item => {
        item.initVal = this.record[item.key]
        item.hidden = !_options.includes(item.key)
        if (item.key === 'field') {
@@ -274,16 +291,6 @@
          }
        } else if (item.key === 'url') {
          item.required = value !== 'qrcode'
        } else if (item.key === 'showInfo') {
          item.initVal = showInfo
        } else if (item.key === 'posterType') {
          item.initVal = posterType
        } else if (item.key === 'fixStyle') {
          item.initVal = fixStyle
        } else if (item.key === 'color') {
          if (value === 'splitline') {
            item.initVal = '#EBE9E9'
          }
        }
        return item
@@ -295,9 +302,6 @@
      }
      this.setState({
        link: '',
        eleType: value,
        showType: card.showType || 'line',
        formlist: _formlist
      }, () => {
        if (value === 'splitline') {
@@ -320,90 +324,27 @@
        this.props.form.setFieldsValue({value: option.props.title})
      }
    } else if (key === 'link') {
      let _options = this.getOptions(eleType, datatype, value, showType, showInfo, fixStyle, posterType)
      let _options = this.getOptions()
      this.setState({
        link: value,
        formlist: this.state.formlist.map(item => {
          item.initVal = this.record[item.key]
          item.hidden = !_options.includes(item.key)
          if (item.key === 'linkurl') {
            item.type = value === 'dynamic' ? 'select' : 'textarea'
          }
          return item
        })
      })
    }
  }
  onChange = (e, key) => {
    const { eleType, datatype, link, showType, showInfo, fixStyle, posterType } = this.state
    let value = e.target.value
    if (key === 'datatype') {
      let _options = this.getOptions(eleType, value, link, showType, showInfo, fixStyle, posterType)
    } else if (['datatype', 'showInfo', 'showType', 'fixStyle', 'posterType', 'eval', 'linkType'].includes(key)) {
      let _options = this.getOptions()
      this.setState({
        datatype: value,
        formlist: this.state.formlist.map(item => {
          item.initVal = this.record[item.key]
          item.hidden = !_options.includes(item.key)
          return item
        })
      })
    } else if (key === 'link') {
      let _options = this.getOptions(eleType, datatype, value, showType, showInfo, fixStyle, posterType)
      this.setState({
        link: value,
        formlist: this.state.formlist.map(item => {
          item.hidden = !_options.includes(item.key)
          if (item.key === 'linkurl') {
            item.type = value === 'dynamic' ? 'select' : 'textarea'
          }
          return item
        })
      })
    } else if (key === 'showInfo') {
      let _options = this.getOptions(eleType, datatype, link, showType, value, fixStyle, posterType)
      this.setState({
        showInfo: value,
        formlist: this.state.formlist.map(item => {
          item.hidden = !_options.includes(item.key)
          return item
        })
      })
    } else if (key === 'showType') {
      this.setState({
        showType: value
      }, () => {
        let _options = this.getOptions(eleType, datatype, link, value, showInfo, fixStyle, posterType)
        this.setState({
          formlist: this.state.formlist.map(item => {
            item.hidden = !_options.includes(item.key)
            return item
          })
        })
      })
    } else if (key === 'fixStyle') {
      this.setState({
        fixStyle: value
      }, () => {
        let _options = this.getOptions(eleType, datatype, link, showType, showInfo, value, posterType)
        this.setState({
          formlist: this.state.formlist.map(item => {
            item.hidden = !_options.includes(item.key)
            return item
          })
        })
      })
    } else if (key === 'posterType') {
      this.setState({
        posterType: value
      }, () => {
        let _options = this.getOptions(eleType, datatype, link, showType, showInfo, fixStyle, value)
        this.setState({
          formlist: this.state.formlist.map(item => {
            item.hidden = !_options.includes(item.key)
            return item
          })
        })
      })
    }
@@ -539,8 +480,8 @@
                  getPopupContainer={() => document.getElementById('card-winter')}
                >
                  {item.options.map((option, index) =>
                    <Select.Option id={`${index}`} title={option.text} key={`${index}`} value={option.value}>
                      {option.text}
                    <Select.Option id={`${index}`} title={option.text || option.label} key={`${index}`} value={option.value}>
                      {option.text || option.label}
                    </Select.Option>
                  )}
                </Select>
@@ -585,7 +526,7 @@
                  message: '请选择' + item.label + '!'
                }]
              })(
                <Radio.Group onChange={(e) => {this.onChange(e, item.key)}} disabled={item.readonly}>
                <Radio.Group onChange={(e) => {this.selectChange(item.key, e.target.value)}} disabled={item.readonly}>
                  {item.options.map(option => {
                    return (
                      <Radio key={option.value} value={option.value}>{option.text}</Radio>
@@ -670,12 +611,33 @@
  }
  handleConfirm = () => {
    const { config } = this.props
    // 表单提交时检查输入值是否正确
    return new Promise((resolve, reject) => {
      this.props.form.validateFieldsAndScroll((err, values) => {
        if (!err) {
          values.uuid = this.props.card.uuid
          values.marks = this.props.card.marks || null
          // eslint-disable-next-line
          if (values.eleType === 'formula' && values.eval !== 'false' && /^[\u4E00-\u9FA50-9a-zA-Z_\s@\+\-\*\/]*$/ig.test(values.formula) && /[\+\-\*\/]/ig.test(values.formula)) {
            let cols = []
            config.subColumns && config.subColumns.forEach(col => {
              if (/^(Int|Decimal)/ig.test(col.datatype)) {
                cols.push({reg: new RegExp('@' + col.field + '@', 'ig'), value: `(@${col.field}@)`})
              }
            })
            config.columns.forEach(col => {
              if (/^(Int|Decimal)/ig.test(col.datatype)) {
                cols.push({reg: new RegExp('@' + col.field + '@', 'ig'), value: `(@${col.field}@)`})
              }
            })
            cols.forEach(col => {
              values.formula = values.formula.replace(col.reg, col.value)
            })
          }
          resolve(values)
        } else {
@@ -704,4 +666,4 @@
  }
}
export default Form.create()(MainSearch)
export default Form.create()(ElementEditForm)
src/menu/components/card/cardcellcomponent/formconfig.jsx
@@ -56,6 +56,58 @@
    width = +width.replace(/x/, '.5')
  }
  let linkTypes = [
    { value: 'tel', text: '电话' },
    { value: 'email', text: '邮箱' },
    { value: 'other', text: '其他' }
  ]
  if (appType === 'mob') {
    linkTypes = [
      { value: 'tel', text: '电话' },
      { value: 'email', text: '邮箱' },
      { value: 'qywx', text: '企业微信' },
      { value: 'linkmenu', text: '关联菜单' },
      { value: 'other', text: '其他' }
    ]
  } else if (appType === 'pc') {
    linkTypes = [
      { value: 'tel', text: '电话' },
      { value: 'email', text: '邮箱' },
      { value: 'linkmenu', text: '关联菜单' },
      { value: 'other', text: '其他' }
    ]
  }
  if (card.linkType === 'qywx') {
    if (appType !== 'mob') {
      card.link = ''
      card.linkType = ''
      card.linkurl = ''
    }
  } else if (card.linkType === 'linkmenu') {
    if (appType !== 'mob' && appType !== 'pc') {
      card.link = ''
      card.linkType = ''
      card.linkurl = ''
      card.linkmenu = ''
    }
  }
  let appMenus = sessionStorage.getItem('appMenus')
  if (['pc', 'mob'].includes(appType)) {
    if (appMenus) {
      try {
        appMenus = JSON.parse(appMenus)
      } catch (e) {
        appMenus = []
      }
    } else {
      appMenus = []
    }
    appMenus.push({value: 'goback', text: '返回(上一页)'})
  }
  let forms = [
    {
      type: 'select',
@@ -167,6 +219,21 @@
      label: '预览地址',
      initVal: card.posterField || '',
      required: true
    },
    {
      type: 'radio',
      key: 'eval',
      label: '解析',
      initVal: card.eval || 'false',
      tooltip: '当公式内容涉及计算时请选择“是”,当公式内容为字段拼接时请选择“否”。',
      required: false,
      options: [{
        value: 'true',
        text: '是'
      }, {
        value: 'false',
        text: '否'
      }]
    },
    {
      type: 'number',
@@ -504,17 +571,12 @@
      forbid: isHeader
    },
    {
      type: 'radio',
      type: linkTypes.length > 4 ? 'select' : 'radio',
      key: 'linkType',
      label: '链接类型',
      initVal: card.linkType || 'other',
      required: false,
      options: [
        { value: 'tel', text: '电话' },
        { value: 'email', text: '邮箱' },
        { value: 'qywx', text: '企业微信' },
        { value: 'other', text: '其他' }
      ]
      options: linkTypes
    },
    {
      type: 'radio',
@@ -529,6 +591,15 @@
    },
    {
      type: 'select',
      key: 'linkmenu',
      label: '关联菜单',
      initVal: card.linkmenu || '',
      required: true,
      options: appMenus || [],
      forbid: !['pc', 'mob'].includes(appType)
    },
    {
      type: 'select',
      key: 'linkurl',
      label: '链接地址',
      initVal: card.linkurl || '',
@@ -537,24 +608,22 @@
    },
    {
      type: 'radio',
      key: 'joint',
      label: '拼接参数',
      initVal: card.joint || 'true',
      required: false,
      options: [{
        value: 'true',
        text: '是'
      }, {
        value: 'false',
        text: '否'
      }]
      key: 'open',
      label: '打开方式',
      initVal: card.open || 'blank',
      tooltip: '菜单打开方式。',
      required: true,
      forbid: !['pc', 'mob'].includes(appType),
      options: [
        {value: 'blank', text: appType !== 'mob' ? '新窗口' : '新页面'},
        {value: 'self', text: appType !== 'mob' ? '当前窗口' : '当前页面'},
      ]
    },
    {
      type: 'radio',
      key: 'eval',
      label: '解析',
      initVal: card.eval || 'false',
      tooltip: '当公式内容涉及计算时请选择“是”,当公式内容为字段拼接时请选择“否”。',
      key: 'joint',
      label: '拼接参数',
      initVal: card.joint || 'true',
      required: false,
      options: [{
        value: 'true',
src/menu/components/card/cardcellcomponent/index.jsx
@@ -624,10 +624,9 @@
  }
  dropButton = (id) => {
    const { cards, cardCell } = this.props
    const { cards } = this.props
    if (!cards.action) return
    if (cardCell.type === 'custom') return
    let index = cards.action.findIndex(item => item.uuid === id)
src/menu/components/card/data-card/options.jsx
@@ -522,13 +522,13 @@
      type: 'radio',
      field: 'permission',
      label: '权限验证',
      initval: wrap.permission || 'false',
      initval: wrap.permission || (!appType ? 'true' : 'false'),
      required: false,
      options: [
        {value: 'true', label: '启用'},
        {value: 'false', label: '禁用'},
      ],
      forbid: !appType || sessionStorage.getItem('editMenuType') === 'popview'
      forbid: sessionStorage.getItem('editMenuType') === 'popview'
    },
    {
      type: 'multiselect',
src/menu/components/card/double-data-card/options.jsx
@@ -233,13 +233,13 @@
      type: 'radio',
      field: 'permission',
      label: '权限验证',
      initval: wrap.permission || 'false',
      initval: wrap.permission || (!appType ? 'true' : 'false'),
      required: false,
      options: [
        {value: 'true', label: '启用'},
        {value: 'false', label: '禁用'},
      ],
      forbid: !appType || sessionStorage.getItem('editMenuType') === 'popview'
      forbid: sessionStorage.getItem('editMenuType') === 'popview'
    },
    {
      type: 'multiselect',
src/menu/components/carousel/data-card/options.jsx
@@ -206,13 +206,13 @@
      type: 'radio',
      field: 'permission',
      label: '权限验证',
      initval: wrap.permission || 'false',
      initval: wrap.permission || (!appType ? 'true' : 'false'),
      required: false,
      options: [
        {value: 'true', label: '启用'},
        {value: 'false', label: '禁用'},
      ],
      forbid: !appType || sessionStorage.getItem('editMenuType') === 'popview'
      forbid: sessionStorage.getItem('editMenuType') === 'popview'
    },
    {
      type: 'multiselect',
src/menu/components/module/voucher/voucherTable/index.scss
@@ -31,10 +31,10 @@
      border-right: 1px solid #e9e9e9;
    }
    span:nth-child(3), span:nth-child(6) {
      border-color: #91d5ff;
      border-color: #474069;
    }
    span:nth-child(9) {
      border-color: #ffa39e;
      border-color: #C48584;
    }
  }
@@ -45,7 +45,7 @@
      tr {
        th {
          position: relative;
          background-color: transparent;
          background-color: #E3E7F2;
          padding: 0;
          height: 60px;
          line-height: 60px;
@@ -83,6 +83,9 @@
      max-width: 60px;
    }
    .ant-table-tbody {
      tr:last-child {
        background-color: #FBF8EF;
      }
      tr td {
        position: relative;
        background-color: transparent;
src/menu/components/share/actioncomponent/actionform/index.jsx
@@ -1000,7 +1000,7 @@
                values.verify.invalid = 'true'
              }
            }
          } else if (values.OpenType === 'tab' && values.linkmenu) {
          } else if (values.OpenType === 'tab' && values.linkmenu && Array.isArray(values.linkmenu)) {
            if (sessionStorage.getItem('thdMenuList')) {
              let list = null
              try {
src/menu/components/share/actioncomponent/formconfig.jsx
@@ -112,6 +112,7 @@
    } else {
      appMenus = []
    }
    appMenus.push({value: 'goback', text: '返回(上一页)'})
  } else {
    menulist = sessionStorage.getItem('fstMenuList')
    if (menulist) {
@@ -819,7 +820,7 @@
      extendName: 'MenuNo',
      required: false,
      allowClear: true,
      options: appType === 'mob' || appType === 'pc' ? [...appMenus, {value: 'goback', text: '返回(上一页)'}] : menulist,
      options: appType === 'mob' || appType === 'pc' ? appMenus : menulist,
      forbid: viewType === 'popview'
    },
    {
src/menu/components/share/actioncomponent/index.jsx
@@ -406,7 +406,7 @@
          } else {
            btn.style = item.style || {}
            if (btn.class) {
              if (btn.class !== item.class || btn.show !== item.show || !btn.style.color || item.focus) {
              if (btn.class !== item.class || btn.show !== item.show || !btn.style.color || (item.focus && !btn.style.color)) {
                if (btn.show === 'icon') {
                  btn.style.color = color[btn.class]
                  btn.style.backgroundColor = 'transparent'
@@ -599,7 +599,7 @@
    let _col = null
    if (config.type === 'table') {
      config.cols.forEach(col => {
        if (col.type !== 'action') return
        if (col.type !== 'custom') return
        col.elements = col.elements.filter(item => {
          if (item.uuid === id) {
src/menu/components/share/pastebasetable/index.jsx
@@ -39,42 +39,27 @@
        return cell
      })
      let loopCol = (col) => {
        col.subcols = col.subcols.map(c => {
          c.uuid = Utils.getuuid()
          if (c.type === 'colspan' && c.subcols) {
            c = loopCol(c)
          } else if (c.type === 'custom' && c.elements) {
            c.elements = c.elements.map(cell => {
              cell.uuid = Utils.getuuid()
              return cell
            })
          }
          return c
        })
        return col
      }
      res.cols = res.cols.map(col => {
      let loopCol = (cols) => {
        return cols.map(col => {
        col.uuid = Utils.getuuid()
          if (col.type === 'action') {
            col.type = 'custom'
          }
        if (col.type === 'colspan' && col.subcols) {
          col = loopCol(col)
            col.subcols = loopCol(col.subcols)
        } else if (col.type === 'custom' && col.elements) {
          col.elements = col.elements.map(cell => {
            cell.uuid = Utils.getuuid()
            return cell
          })
        } else if (col.type === 'action' && col.elements) {
          col.elements = col.elements.map(cell => {
            cell.uuid = Utils.getuuid()
            return cell
          })
        }
        return col
      })
      }
      res.cols = loopCol(res.cols)
      let oriUids = {}
      res.action = res.action.map(cell => {
src/menu/components/share/pastecomponent/index.jsx
@@ -74,41 +74,27 @@
        })
      }
    } else if (item.copyType === 'cols') {
      let loopCol = (col) => {
        col.subcols = col.subcols.map(c => {
          c.uuid = Utils.getuuid()
      let loopCol = (cols) => {
        return cols.map(col => {
          col.uuid = Utils.getuuid()
          if (c.type === 'colspan' && c.subcols) {
            c = loopCol(c)
          } else if (c.type === 'custom' && c.elements) {
            c.elements = c.elements.map(cell => {
          if (col.type === 'action') {
            col.type = 'custom'
          }
          if (col.type === 'colspan' && col.subcols) {
            col.subcols = loopCol(col.subcols)
          } else if (col.type === 'custom' && col.elements) {
            col.elements = col.elements.map(cell => {
              cell.uuid = Utils.getuuid()
              return cell
            })
          }
          return c
        })
        return col
        })
      }
      item.cols = item.cols.map(_item => {
        _item.uuid = Utils.getuuid()
        if (_item.type === 'colspan' && _item.subcols) {
          _item = loopCol(_item)
        } else if (_item.type === 'custom' && _item.elements) {
          _item.elements = _item.elements.map(cell => {
            cell.uuid = Utils.getuuid()
            return cell
          })
        } else if (_item.type === 'action' && _item.elements) {
          _item.elements = _item.elements.map(cell => {
            cell.uuid = Utils.getuuid()
            return cell
          })
        }
        return _item
      })
      item.cols = loopCol(item.cols)
    }
    return item
src/menu/components/share/usercomponent/index.jsx
@@ -82,36 +82,30 @@
      return item
    })
    _config.cols = _config.cols.map(col => {
    let loopCol = (cols) => {
      return cols.map(col => {
        col.uuid = Utils.getuuid()
        col.marks = null
      if (col.type === 'colspan' && col.subcols) {
        col = this.loopCol(col)
          col.subcols = loopCol(col.subcols)
      } else if (col.type === 'custom' && col.elements) {
        col.elements = col.elements.map(cell => this.resetElement(cell))
      } else if (col.type === 'action' && col.elements) {
        col.elements = col.elements.map(cell => {
            if (cell.eleType === 'button') {
          cell.verify = null
            } else {
              cell = this.resetElement(cell)
            }
          return cell
        })
      }
      col.marks = null
      return col
    })
    }
    _config.cols = loopCol(_config.cols)
    return _config
  }
  loopCol = (col) => {
    col.subcols = col.subcols.map(c => {
      if (c.type === 'colspan' && c.subcols) {
        c = this.loopCol(c)
      } else if (c.type === 'custom' && c.elements) {
        c.elements = c.elements.map(cell => this.resetElement(cell))
      }
      c.marks = null
      return c
    })
    return col
  }
  resetElement = (item) => {
src/menu/components/table/base-table/columns/editColumn/formconfig.jsx
@@ -58,11 +58,9 @@
    text: '序号'
  }]
  if (!card.isSub) {
    options.push({
      value: 'action',
      text: '操作'
    })
  let decimal = card.decimal === undefined ? 0 : card.decimal
  if (card.type === 'formula' && typeof(card.decimal) !== 'number') {
    decimal = ''
  }
  return [
@@ -71,7 +69,11 @@
      key: 'label',
      label: '列头文字',
      initVal: card.label,
      required: true
      required: true,
      rules: [{
        max: 100,
        message: '最多100个字符。'
      }]
    },
    {
      type: 'select',
@@ -87,14 +89,25 @@
      label: '字段',
      initVal: card.field,
      required: true,
      options: card.isSub ? fields : []
      options: card.isSub ? fields : [],
      rules: [{
        pattern: /^[\u4E00-\u9FA50-9a-zA-Z_]*$/ig,
        message: '字段名只允许包含数字、字母、汉字以及_'
      }, {
        max: 100,
        message: '最多100个字符。'
      }]
    },
    {
      type: 'text',
      key: 'nameField',
      label: '名称字段',
      initVal: card.nameField || '',
      required: false
      required: false,
      rules: [{
        max: 100,
        message: '最多100个字符。'
      }]
    },
    {
      type: 'number',
@@ -147,6 +160,18 @@
        value: 'false',
        text: '否'
      }]
    },
    {
      type: 'radio',
      key: 'eval',
      label: '解析',
      initVal: card.eval || 'false',
      tooltip: '当公式内容涉及计算时请选择“是”,当公式内容为字段拼接时请选择“否”。',
      required: false,
      options: [
        { value: 'true', text: '是' },
        { value: 'false', text: '否' }
      ]
    },
    {
      type: 'radio',
@@ -231,7 +256,7 @@
      max: 18,
      decimal: 0,
      label: '小数位',
      initVal: card.decimal === undefined ? 0 : card.decimal,
      initVal: decimal,
      required: !card.isSub
    },
    {
@@ -280,7 +305,11 @@
      label: '前缀',
      initVal: card.prefix || '',
      required: false,
      readonly: false
      readonly: false,
      rules: [{
        max: 100,
        message: '最多100个字符。'
      }]
    },
    {
      type: 'text',
@@ -288,7 +317,11 @@
      label: '后缀',
      initVal: card.postfix || '',
      required: false,
      readonly: false
      readonly: false,
      rules: [{
        max: 100,
        message: '最多100个字符。'
      }]
    },
    {
      type: 'number',
@@ -390,18 +423,6 @@
      initVal: card.linkfields || [],
      required: false,
      options: fields,
    },
    {
      type: 'radio',
      key: 'eval',
      label: '解析',
      initVal: card.eval || 'false',
      tooltip: '当公式内容涉及计算时请选择“是”,当公式内容为字段拼接时请选择“否”。',
      required: false,
      options: [
        { value: 'true', text: '是' },
        { value: 'false', text: '否' }
      ]
    },
    {
      type: 'textarea',
src/menu/components/table/base-table/columns/editColumn/index.jsx
@@ -1,11 +1,10 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import { is, fromJS } from 'immutable'
import { Form, Row, Col, Input, Select, InputNumber, Radio, Tooltip, Cascader, Modal, Checkbox } from 'antd'
import { Form, Row, Col, Input, Select, InputNumber, Radio, Tooltip, Cascader, Modal, Checkbox, Popover } from 'antd'
import { QuestionCircleOutlined } from '@ant-design/icons'
import { getColumnForm } from './formconfig'
import { formRule } from '@/utils/option.js'
import './index.scss'
const { TextArea } = Input
@@ -25,7 +24,6 @@
class NormalTableColumn extends Component {
  static propTpyes = {
    visible: PropTypes.bool,
    column: PropTypes.object,
    fields: PropTypes.array,
    submitCol: PropTypes.func,  // 提交事件
@@ -36,6 +34,8 @@
    visible: false,
    formlist: null
  }
  record = null
  UNSAFE_componentWillReceiveProps (nextProps) {
    if (nextProps.column && !is(fromJS(this.props.column), fromJS(nextProps.column))) {
@@ -50,20 +50,26 @@
    })
    
    let formlist = getColumnForm(column, fields)
    let _options = fromJS(columnTypeOptions[column.type]).toJS()
    if (column.type === 'text' || column.type === 'number') {
      if (column.perspective === 'linkmenu') {
        _options.push('linkmenu', 'linkfields', 'open')
      } else if (column.perspective === 'linkurl') {
        _options.push('linkurl', 'linkfields', 'open')
      }
    }
    this.record = {}
    formlist.forEach(item => {
      this.record[item.key] = item.initVal
    })
    let _options = this.getOptions()
    this.setState({
      visible: true,
      type: column.type,
      formlist: formlist.map(item => {
        item.hidden = !_options.includes(item.key)
        if (item.key === 'formula') {
          item.fields = this.props.fields.map(col => col.field)
          item.fields = item.fields.join(', ')
        } else if (this.record.type === 'formula' && item.key === 'decimal') {
          item.required = false
        }
        return item
      })
@@ -80,13 +86,41 @@
    }
  }
  getOptions = () => {
    let _options = fromJS(columnTypeOptions[this.record.type]).toJS()
    if (this.record.type === 'text' || this.record.type === 'number') {
      if (this.record.perspective === 'linkmenu') {
        _options.push('linkmenu', 'linkfields', 'open')
      } else if (this.record.perspective === 'linkurl') {
        _options.push('linkurl', 'linkfields', 'open')
      }
    }
    if (this.record.type === 'formula' && this.record.eval === 'true') {
      _options.push('decimal')
    }
    return _options
  }
  typeChange = (key, value, option) => {
    const { column } = this.props
    this.record[key] = value
    if (key === 'type') {
      let _options = fromJS(columnTypeOptions[value]).toJS()
      let _options = this.getOptions()
      this.setState({
        type: value,
        formlist: this.state.formlist.map(item => {
          if (item.key === 'decimal') {
            item.required = !(column.isSub || value === 'formula')
            if (value === 'formula') {
              this.record.decimal = ''
            }
          }
          item.initVal = this.record[item.key]
          item.hidden = !_options.includes(item.key)
          return item
@@ -98,8 +132,6 @@
          this.props.form.setFieldsValue({perspective: ''})
        } else if (value === 'colspan') {
          this.props.form.setFieldsValue({Align: 'center'})
        } else if (value === 'action') {
          this.props.form.setFieldsValue({Align: 'center', label: '操作'})
        } else if (value === 'index') {
          this.props.form.setFieldsValue({label: '序号'})
        }
@@ -117,13 +149,18 @@
        values.type = 'text'
      }
      if (values.type !== this.state.type) {
      let _type = this.record.type
      this.record.type = values.type
      if (values.type !== _type) {
        values.perspective = ''
        let _options = fromJS(columnTypeOptions[values.type]).toJS()
        this.record.perspective = ''
        let _options = this.getOptions()
        this.setState({
          type: values.type,
          formlist: this.state.formlist.map(item => {
            item.initVal = this.record[item.key]
            item.hidden = !_options.includes(item.key)
            return item
@@ -136,21 +173,12 @@
      }
    } else if (key === 'format' && value === 'percent') {
      this.props.form.setFieldsValue({postfix: '%'})
    }
  }
  changeRadio = (key, value) => {
    if (key === 'perspective') {
      let _options = fromJS(columnTypeOptions[this.state.type]).toJS()
      if (value === 'linkmenu') {
        _options.push('linkmenu', 'linkfields', 'open')
      } else if (value === 'linkurl') {
        _options.push('linkurl', 'linkfields', 'open')
      }
    } else if (['perspective', 'eval'].includes(key)) {
      let _options = this.getOptions()
      this.setState({
        formlist: this.state.formlist.map(item => {
          item.initVal = this.record[item.key]
          item.hidden = !_options.includes(item.key)
          return item
@@ -170,21 +198,6 @@
      if (item.hidden || item.forbid) return
      if (item.type === 'text') {
        let rules = []
        if (item.key === 'field') {
          rules = [{
            pattern: /^[\u4E00-\u9FA50-9a-zA-Z_]*$/ig,
            message: '字段名只允许包含数字、字母、汉字以及_'
          }, {
            max: formRule.input.max,
            message: formRule.input.message
          }]
        } else if (item.key !== 'linkurl') {
          rules = [{
            max: formRule.input.max,
            message: formRule.input.message
          }]
        }
        fields.push(
          <Col span={12} key={index}>
            <Form.Item label={item.tooltip ?
@@ -200,7 +213,7 @@
                    required: !!item.required,
                    message: '请输入' + item.label + '!'
                  },
                  ...rules
                  ...item.rules
                ]
              })(<Input placeholder="" autoComplete="off" disabled={item.readonly} onPressEnter={this.handleSubmit} />)}
            </Form.Item>
@@ -275,14 +288,10 @@
                  }
                ]
              })(
                <Radio.Group onChange={(e) => {this.changeRadio(item.key, e.target.value)}}>
                  {
                    item.options.map(option => {
                      return (
                        <Radio key={option.value} value={option.value}>{option.text}</Radio>
                      )
                    })
                  }
                <Radio.Group onChange={(e) => {this.typeChange(item.key, e.target.value)}}>
                  {item.options.map(option => {
                    return (<Radio key={option.value} value={option.value}>{option.text}</Radio>)
                  })}
                </Radio.Group>
              )}
            </Form.Item>
@@ -350,6 +359,31 @@
          </Col>
        )
      } else if (item.type === 'textarea') {
        if (item.key === 'formula') {
          fields.push(
            <Col span={24} className="textarea" key={index}>
              <Form.Item label={item.tooltip ?
                <Tooltip placement="topLeft" title={item.tooltip}>
                  <QuestionCircleOutlined className="mk-form-tip" />
                  {item.label}
                </Tooltip> : item.label
              }>
                {getFieldDecorator(item.key, {
                  initialValue: item.initVal || '',
                  rules: [
                    {
                      required: !!item.required,
                      message: '请输入' + item.label + '!'
                    }
                  ]
                })(<TextArea autoSize={{minRows: 2}} disabled={item.readonly} placeholder={item.placeholder || ''} />)}
              </Form.Item>
              <Popover overlayClassName="formula-fields" placement="topLeft" title="" content={<div>{item.fields}</div>} trigger="click">
                <span className="formula-icon">字段集</span>
              </Popover>
            </Col>
          )
        } else {
        fields.push(
          <Col span={24} key={index} className="textarea">
            <Form.Item label={item.tooltip ?
@@ -371,14 +405,30 @@
          </Col>
        )
      }
      }
    })
    return fields
  }
  handleSubmit = () => {
    const { fields } = this.props
    // 表单提交时检查输入值是否正确
    this.props.form.validateFieldsAndScroll((err, values) => {
      if (!err) {
        // eslint-disable-next-line
        if (values.type === 'formula' && values.eval !== 'false' && /^[\u4E00-\u9FA50-9a-zA-Z_\s@\+\-\*\/]*$/ig.test(values.formula) && /[\+\-\*\/]/ig.test(values.formula)) {
          let cols = []
          fields.forEach(col => {
            if (/^(Int|Decimal)/ig.test(col.datatype)) {
              cols.push({reg: new RegExp('@' + col.field + '@', 'ig'), value: `(@${col.field}@)`})
            }
          })
          cols.forEach(col => {
            values.formula = values.formula.replace(col.reg, col.value)
          })
        }
        this.props.submitCol(values, () => {
          this.setState({visible: false, formlist: null})
        })
src/menu/components/table/base-table/columns/editColumn/index.scss
@@ -14,9 +14,27 @@
      width: 88%;
    }
  }
  .formula-icon {
    position: absolute;
    bottom: 5px;
    right: 15px;
    cursor: pointer;
    font-size: 12px;
    color: #1890ff;
  }
  >.ant-row >.ant-col {
    display: inline-block;
    vertical-align: top;
    float: none;
  }
}
.formula-fields {
  z-index: 1200!important;
  .ant-popover-inner-content {
    div {
      max-width: 750px;
      word-break: break-all;
    }
  }
}
src/menu/components/table/base-table/columns/index.jsx
@@ -3,7 +3,7 @@
import { is, fromJS } from 'immutable'
import { DndProvider, DragSource, DropTarget } from 'react-dnd'
import { Table, Popover, Modal, message, notification } from 'antd'
import { PlusOutlined, EditOutlined, CopyOutlined, DeleteOutlined, FontColorsOutlined, CloseCircleOutlined, AntDesignOutlined, InfoOutlined } from '@ant-design/icons'
import { PlusOutlined, PlusSquareOutlined, EditOutlined, CopyOutlined, DeleteOutlined, FontColorsOutlined, CloseCircleOutlined, AntDesignOutlined, InfoOutlined } from '@ant-design/icons'
import asyncComponent from '@/utils/asyncComponent'
import asyncIconComponent from '@/utils/asyncIconComponent'
@@ -53,7 +53,7 @@
  render() {
    const { connectDragSource, connectDropTarget, moveCol, addElement, dropCol, updateCol, editColumn, pasteCell, changeStyle, deleteCol, index, column, align, fields, children, ...restProps } = this.props
    if (index !== undefined) {
    if (index !== undefined && column) {
      let style = {cursor: 'move', textAlign: align}
      if (column.Width) {
        style.width = column.Width
@@ -65,17 +65,17 @@
      }
      return connectDragSource(
        connectDropTarget(<th {...restProps} index={index} style={style} onDoubleClick={() => column && this.props.editColumn(column)}>
        connectDropTarget(<th {...restProps} index={index} style={style} onDoubleClick={() => this.props.editColumn(column)}>
          <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={
            <div className="mk-popover-control" onDoubleClick={(e) => e.stopPropagation()}>
              {column && ['custom', 'colspan', 'action'].includes(column.type) ?
                <PlusOutlined className="plus" title="添加" onClick={() => this.props.addElement(column)} /> : null
              }
              {column.type === 'colspan' ? <PlusOutlined className="plus" title="添加列" onClick={() => this.props.addElement(column)} /> : null}
              {column.type === 'custom' ? <PlusOutlined className="plus" title="添加元素" onClick={() => this.props.addElement(column)} /> : null}
              {column.type === 'custom' ? <PlusSquareOutlined className="plus" title="添加按钮" onClick={() => this.props.addElement(column, 'button')} /> : null}
              <EditOutlined className="edit" title="编辑" onClick={() => this.props.editColumn(column)} />
              {column && column.type === 'custom' ? <PasteComponent options={['customCardElement']} updateConfig={(res, resolve) => this.props.pasteCell(column, res, resolve)} /> : null}
              {column && (column.type === 'custom' || column.type === 'action') ? <FontColorsOutlined className="style" title="调整样式" onClick={() => this.props.changeStyle(column)}/> : null}
              {column.type === 'custom' ? <PasteComponent options={['customCardElement', 'action']} updateConfig={(res, resolve) => this.props.pasteCell(column, res, resolve)} /> : null}
              {column.type === 'custom' ? <FontColorsOutlined className="style" title="调整样式" onClick={() => this.props.changeStyle(column)}/> : null}
              <DeleteOutlined className="close" title="删除" onClick={this.deleteCol} />
              {column && ['text', 'number', 'formula'].includes(column.type) ? <MarkColumn field={column.field || ''} columns={fields} marks={column.marks} onSubmit={this.updateMarks} /> : null }
              {['text', 'number', 'formula'].includes(column.type) ? <MarkColumn field={column.field || ''} columns={fields} marks={column.marks} onSubmit={this.updateMarks} /> : null }
            </div>
          } trigger="hover">
            {children}
@@ -97,13 +97,13 @@
        <th {...restProps} style={style} key={column.uuid} onDoubleClick={() => this.props.editColumn(column)}>
          <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={
            <div className="mk-popover-control" onDoubleClick={(e) => e.stopPropagation()}>
              {column && ['custom', 'colspan'].includes(column.type) ?
                <PlusOutlined className="plus" title="添加" onClick={() => this.props.addElement(column)} /> : null
              }
              {column.type === 'colspan' ? <PlusOutlined className="plus" title="添加列" onClick={() => this.props.addElement(column)} /> : null}
              {column.type === 'custom' ? <PlusOutlined className="plus" title="添加元素" onClick={() => this.props.addElement(column)} /> : null}
              {column.type === 'custom' ? <PlusSquareOutlined className="plus" title="添加按钮" onClick={() => this.props.addElement(column, 'button')} /> : null}
              <EditOutlined className="edit" title="编辑" onClick={() => this.props.editColumn(column)} />
              {column.type === 'custom' ? <PasteComponent options={['customCardElement']} updateConfig={(res, resolve) => this.props.pasteCell(column, res, resolve)} /> : null}
              {column.type === 'custom' ? <PasteComponent options={['customCardElement', 'action']} updateConfig={(res, resolve) => this.props.pasteCell(column, res, resolve)} /> : null}
              <DeleteOutlined className="close" title="删除" onClick={this.deleteCol} />
              {column && ['text', 'number', 'formula'].includes(column.type) ? <MarkColumn field={column.field || ''} columns={fields} marks={column.marks} onSubmit={this.updateMarks} /> : null }
              {['text', 'number', 'formula'].includes(column.type) ? <MarkColumn field={column.field || ''} columns={fields} marks={column.marks} onSubmit={this.updateMarks} /> : null }
            </div>
          } trigger="hover">
            {children}
@@ -200,12 +200,6 @@
    if (column && column.type === 'custom') {
      return (
        <td style={{padding: 0, ...(column.style || {})}} className={className}>
          <CardCellComponent cards={config} cardCell={column} elements={column.elements} updateElement={this.updateCard}/>
        </td>
      )
    } else if (column && column.type === 'action') {
      return (
        <td style={{padding: 0, textAlign: column.Align, ...(column.style || {})}} className={'action-column ' + className}>
          <CardCellComponent cards={config} cardCell={column} elements={column.elements} updateElement={this.updateCard}/>
        </td>
      )
@@ -322,11 +316,9 @@
  dropCol = (item, hoverIndex) => {
    let _columns = fromJS(this.state.columns).toJS()
    let col = { focus: true, uuid: Utils.getuuid(), label: 'label', field: '', type: item.subType, elements: [] }
    let col = { focus: true, uuid: Utils.getuuid(), Width: 120, label: 'label', field: '', type: item.subType, elements: [] }
    if (col.type === 'colspan') {
      col.subcols = []
    } else if (col.type === 'action') {
      col.label = '操作'
    } else if (col.type === 'index') {
      col.label = '序号'
    }
@@ -381,14 +373,23 @@
  pasteCell = (col, cell, resolve) => {
    resolve({status: true})
    
    delete cell.copyType
    cell.uuid = Utils.getuuid()
    cell.focus = true
    if (!cell.eleType) {
      if (cell.copyType === 'action') {
        cell.eleType = 'button'
        cell.width = cell.width || 12
      } else {
        cell.eleType = 'text'
      }
    }
    delete cell.copyType
    
    MKEmitter.emit('cardAddElement', col.uuid, cell)
  }
  addElement = (col) => {
  addElement = (col, type) => {
    let column = fromJS(col).toJS()
    if (column.type === 'colspan') {
@@ -401,11 +402,7 @@
      })
      this.updateCol(column)
    } else if (column.type === 'custom') {
      let newcard = {uuid: Utils.getuuid(), focus: true, width: 24, eleType: 'text', datatype: 'dynamic', style: {paddingLeft: '4px'}}
      // 注册事件-添加元素
      MKEmitter.emit('cardAddElement', column.uuid, newcard)
    } else if (column.type === 'action') {
      if (type === 'button') {
      let newcard = {
        uuid: Utils.getuuid(),
        focus: true,
@@ -421,6 +418,12 @@
      // 注册事件-添加元素
      MKEmitter.emit('cardAddElement', column.uuid, newcard)
      } else {
        let newcard = {uuid: Utils.getuuid(), focus: true, width: 24, eleType: 'text', datatype: 'dynamic', style: {paddingLeft: '4px'}}
        // 注册事件-添加元素
        MKEmitter.emit('cardAddElement', column.uuid, newcard)
      }
    }
  }
@@ -436,9 +439,6 @@
    } else if (col.type === 'custom') {
      col.style = card.style || {}
      col.elements = card.type === 'custom' ? (card.elements || []) : []
    } else if (col.type === 'action') {
      col.style = card.style || {}
      col.elements = card.type === 'action' ? (card.elements || []) : []
    }
    if (!col.field || col.isSub) {
src/menu/components/table/base-table/columns/index.scss
@@ -36,11 +36,6 @@
        }
      }
    }
    .action-column {
      .card-detail-row:empty {
        min-height: 40px;
      }
    }
    tr:hover td {
      background: #ffffff!important;
    }
src/menu/components/table/base-table/index.jsx
@@ -99,39 +99,6 @@
    MKEmitter.removeListener('completeSave', this.completeSave)
  }
  // updateFix = (card) => {
  //   let fixs = {}
  //   card.cols.forEach(col => {
  //     if (!col.field) return
  //     if (col.postfix || col.prefix) {
  //       fixs[col.field] = col
  //     }
  //   })
  //   card.cols.forEach(col => {
  //     if (col.type === 'custom') {
  //       col.elements.forEach(cell => {
  //         if (cell.datatype === 'dynamic') {
  //           cell.height = ''
  //           cell.innerHeight = 'auto'
  //           if (fixs[cell.field]) {
  //             if (!cell.prefix && fixs[cell.field].prefix) {
  //               cell.prefix = fixs[cell.field].prefix
  //             }
  //             if (!cell.postfix && fixs[cell.field].postfix) {
  //               cell.postfix = fixs[cell.field].postfix
  //             }
  //           }
  //         }
  //       })
  //     }
  //   })
  //   return card
  // }
  completeSave = () => {
    const { card } = this.state
@@ -255,8 +222,13 @@
    let _actions = [...action]
    cols.forEach(col => {
      if (col.type !== 'action') return
      _actions.push(...col.elements)
      if (col.type === 'custom') {
        col.elements.forEach(cell => {
          if (cell.eleType !== 'button') return
          _actions.push(cell)
        })
      }
    })
    return getWrapForm(wrap, _actions, columns)
src/menu/components/table/edit-table/columns/editColumn/formconfig.jsx
@@ -14,7 +14,6 @@
    roleList = []
  }
  // if (['picture', 'link', 'colspan'].includes(card.type)) {
  if (['picture', 'link'].includes(card.type)) {
    card.type = 'text'
  }
@@ -34,9 +33,6 @@
  }, {
    value: 'colspan',
    text: '合并列'
  // }, {
  //   value: 'action',
  //   text: '操作'
  }, {
    value: 'formula',
    text: '公式'
@@ -44,13 +40,6 @@
    value: 'index',
    text: '序号'
  }]
  if (!card.isSub) {
    options.push({
      value: 'action',
      text: '操作'
    })
  }
  let editCols = [
    {
@@ -148,6 +137,18 @@
    },
    {
      type: 'radio',
      key: 'eval',
      label: '解析',
      initVal: card.eval || 'false',
      tooltip: '当公式内容涉及计算时请选择“是”,当公式内容为字段拼接时请选择“否”。',
      required: false,
      options: [
        { value: 'true', text: '是' },
        { value: 'false', text: '否' }
      ]
    },
    {
      type: 'radio',
      key: 'Align',
      label: '对齐方式',
      initVal: card.Align || 'left',
@@ -163,21 +164,6 @@
        text: '右对齐'
      }]
    },
    // {
    //   type: 'radio',
    //   key: 'sum',
    //   label: '显示合计',
    //   initVal: card.sum || 'false',
    //   tooltip: '合计信息只在使用系统数据源时有效。',
    //   required: false,
    //   options: [{
    //     value: 'true',
    //     text: '是'
    //   }, {
    //     value: 'false',
    //     text: '否'
    //   }]
    // },
    {
      type: 'radio',
      key: 'editable',
@@ -259,16 +245,6 @@
        text: '数据源'
      }]
    },
    // {
    //   type: 'select',
    //   key: 'editField',
    //   label: '编辑字段',
    //   initVal: card.editField || '',
    //   tooltip: '当值与提示文字不同时,可额外添加编辑字段,作为实际值的录入字段。',
    //   allowClear: true,
    //   required: false,
    //   options: fields
    // },
    {
      type: 'options',
      key: 'options',
@@ -392,23 +368,6 @@
      tooltip: '多个值用逗号分隔。',
      required: false
    },
    // {
    //   type: 'radio',
    //   key: 'footEnter',
    //   label: '末行回车',
    //   initVal: card.footEnter || 'false',
    //   tooltip: '新增功能仅在表格可新增时有效。',
    //   options: [{
    //     value: 'sub',
    //     text: '提交'
    //   }, {
    //     value: 'add',
    //     text: '新增'
    //   }, {
    //     value: 'false',
    //     text: '无动作'
    //   }]
    // },
    {
      type: 'number',
      key: 'decimal',
@@ -416,7 +375,7 @@
      max: 18,
      precision: 0,
      label: '小数位',
      initVal: card.decimal || 0,
      initVal: card.decimal,
      required: false
    },
    {
@@ -488,18 +447,6 @@
      label: '后缀',
      initVal: card.postfix || '',
      required: false,
    },
    {
      type: 'radio',
      key: 'eval',
      label: '解析',
      initVal: card.eval || 'false',
      tooltip: '当公式内容涉及计算时请选择“是”,当公式内容为字段拼接时请选择“否”。',
      required: false,
      options: [
        { value: 'true', text: '是' },
        { value: 'false', text: '否' }
      ]
    },
    {
      type: 'textarea',
src/menu/components/table/edit-table/columns/editColumn/index.jsx
@@ -17,18 +17,17 @@
const { TextArea } = Input
const columnTypeOptions = {
  text: ['label', 'field', 'type', 'Align', 'Hide', 'IsSort', 'Width', 'prefix', 'postfix', 'textFormat', 'editable', 'initval', 'blacklist'],
  number: ['label', 'field', 'type', 'Align', 'Hide', 'IsSort', 'Width', 'decimal', 'format', 'prefix', 'postfix', 'editable', 'initval', 'sum', 'blacklist', 'noValue'],
  number: ['label', 'field', 'type', 'Align', 'Hide', 'IsSort', 'Width', 'decimal', 'format', 'prefix', 'postfix', 'editable', 'initval', 'sum', 'blacklist'],
  textarea: ['label', 'field', 'type', 'Align', 'Hide', 'Width', 'prefix', 'initval', 'postfix', 'blacklist'],
  custom: ['label', 'type', 'Align', 'Width', 'blacklist'],
  colspan: ['label', 'type', 'Align', 'Hide', 'blacklist'],
  action: ['label', 'type', 'Align', 'Width'],
  formula: ['label', 'type', 'Align', 'Hide', 'Width', 'prefix', 'postfix', 'eval', 'formula', 'blacklist', 'noValue'],
  formula: ['label', 'type', 'Align', 'Hide', 'Width', 'prefix', 'postfix', 'eval', 'formula', 'blacklist'],
  index: ['label', 'type', 'Align', 'Width']
}
class EdiTableColumn extends Component {
  static propTpyes = {
    visible: PropTypes.bool,
    column: PropTypes.object,
    columns: PropTypes.array,
    fields: PropTypes.array,
@@ -43,7 +42,7 @@
    transfield: {}
  }
  column = null
  record = null
  UNSAFE_componentWillMount() {
    let transfield = {}
@@ -61,22 +60,22 @@
  }
  getOptions = () => {
    let _options = fromJS(columnTypeOptions[this.column.type]).toJS()
    let _options = fromJS(columnTypeOptions[this.record.type]).toJS()
    if (this.column.editable === 'true') {
    if (['number', 'text'].includes(this.record.type) && this.record.editable === 'true') {
      _options.push('ctrlField')
      if (this.column.ctrlField) {
      if (this.record.ctrlField) {
        _options.push('ctrlValue')
      }
      if (this.column.type === 'text') {
      if (this.record.type === 'text') {
        _options.push('editType')
        if (this.column.editType === 'switch') {
        if (this.record.editType === 'switch') {
          _options.push('enter', 'openVal', 'closeVal', 'openText', 'closeText', 'editField')
        } else if (this.column.editType === 'select') {
        } else if (this.record.editType === 'select') {
          _options.push('required', 'enter', 'resourceType', 'linkSubField', 'editField', 'dropdown')
          if (this.column.resourceType === '0') {
          if (this.record.resourceType === '0') {
            _options.push('options')
          } else {
            _options.push('dataSource', 'valueField', 'valueText', 'orderBy', 'orderType', 'disableField', 'database')
@@ -84,9 +83,15 @@
        } else {
          _options.push('required', 'enter')
        }
      } else if (this.column.type === 'number') {
      } else if (this.record.type === 'number') {
        _options.push('max', 'min', 'enter')
      }
    }
    if (this.record.type === 'formula' && this.record.eval === 'true') {
      _options.push('decimal')
    }
    if (['number', 'formula'].includes(this.record.type) && this.record.Hide !== 'true') {
      _options.push('noValue')
    }
    return _options
@@ -99,10 +104,11 @@
    })
    let formlist = getColumnForm(column, fields, this.props.columns)
    this.record = {}
    this.column = fromJS(column).toJS()
    this.column.editType = this.column.editType || 'text'
    this.column.resourceType = this.column.resourceType || '0'
    formlist.forEach(item => {
      this.record[item.key] = item.initVal
    })
    
    let _options = this.getOptions()
@@ -132,7 +138,7 @@
  }
  typeChange = (key, value, option) => {
    this.column[key] = value
    this.record[key] = value
    if (key === 'type') {
      let _options = this.getOptions()
@@ -144,7 +150,11 @@
      this.setState({
        formlist: this.state.formlist.map(item => {
          item.initVal = this.column[item.key] || item.initVal
          if (item.key === 'decimal' && value === 'formula') {
            this.record.decimal = ''
          }
          item.initVal = this.record[item.key]
          item.hidden = !_options.includes(item.key)
          return item
@@ -154,8 +164,6 @@
          this.props.form.setFieldsValue({Align: 'center'})
        } else if (value === 'formula' && _field) {
          this.props.form.setFieldsValue({formula: '@' + _field + '@'})
        } else if (value === 'action') {
          this.props.form.setFieldsValue({Align: 'center', label: '操作'})
        } else if (value === 'index') {
          this.props.form.setFieldsValue({label: '序号'})
        }
@@ -173,15 +181,15 @@
        values.type = 'text'
      }
      let _type = this.column.type
      this.column.type = values.type
      let _type = this.record.type
      this.record.type = values.type
      if (values.type !== _type) {
        let _options = this.getOptions()
        this.setState({
          formlist: this.state.formlist.map(item => {
            item.initVal = this.column[item.key] || item.initVal
            item.initVal = this.record[item.key]
            item.hidden = !_options.includes(item.key)
            return item
@@ -194,12 +202,12 @@
      }
    } else if (key === 'format' && value === 'percent') {
      this.props.form.setFieldsValue({postfix: '%'})
    } else if (key === 'editable' || key === 'editType' || key === 'resourceType' || key === 'ctrlField') {
    } else if (['editable', 'editType', 'resourceType', 'ctrlField', 'eval', 'Hide'].includes(key)) {
      let _options = this.getOptions()
      this.setState({
        formlist: this.state.formlist.map(item => {
          item.initVal = this.column[item.key] || item.initVal
          item.initVal = this.record[item.key]
          item.hidden = !_options.includes(item.key)
          return item
@@ -211,7 +219,7 @@
  multiselectChange = (key, value) => {
    if (key !== 'linkSubField') return
    this.column[key] = value
    this.record[key] = value
  }
  handleEmpty = () => {
@@ -249,7 +257,7 @@
  }
  changeOptions = (data) => {
    this.column.options = data || []
    this.record.options = data || []
  }
  getFields() {
@@ -371,7 +379,7 @@
        span = 24
        className = 'text-area'
        let linkSubFields = this.column.linkSubField || []
        let linkSubFields = this.record.linkSubField || []
      
        content = <EditTable type={'select'} module="form" transfield={transfield} linkSubFields={linkSubFields} onChange={this.changeOptions}/>
      }
@@ -396,6 +404,7 @@
  }
  handleSubmit = () => {
    const { fields } = this.props
    // 表单提交时检查输入值是否正确
    this.props.form.validateFieldsAndScroll((err, values) => {
      if (!err) {
@@ -408,6 +417,18 @@
            })
            return
          }
          // eslint-disable-next-line
        } else if (values.type === 'formula' && values.eval !== 'false' && /^[\u4E00-\u9FA50-9a-zA-Z_\s@\+\-\*\/]*$/ig.test(values.formula) && /[\+\-\*\/]/ig.test(values.formula)) {
          let cols = []
          fields.forEach(col => {
            if (/^(Int|Decimal)/ig.test(col.datatype)) {
              cols.push({reg: new RegExp('@' + col.field + '@', 'ig'), value: `(@${col.field}@)`})
            }
          })
          cols.forEach(col => {
            values.formula = values.formula.replace(col.reg, col.value)
          })
        }
        if (values.dataSource && /\s/.test(values.dataSource)) {
@@ -448,7 +469,7 @@
            if (result.status) {
              this.setState({visible: false, loading: false, formlist: null})
              this.props.submitCol(values)
              this.column = null
              this.record = null
            } else {
              this.setState({loading: false})
              Modal.error({
@@ -459,7 +480,7 @@
        } else {
          this.setState({visible: false, formlist: null})
          this.props.submitCol(values)
          this.column = null
          this.record = null
        }
      }
    })
src/menu/components/table/edit-table/columns/index.jsx
@@ -3,7 +3,7 @@
import { is, fromJS } from 'immutable'
import { DndProvider, DragSource, DropTarget } from 'react-dnd'
import { Table, Popover, Modal, message, Button, Typography } from 'antd'
import { PlusOutlined, FileSyncOutlined, EditOutlined, CopyOutlined, DeleteOutlined, FontColorsOutlined, CloseCircleOutlined, AntDesignOutlined } from '@ant-design/icons'
import { PlusOutlined, PlusSquareOutlined, FileSyncOutlined, EditOutlined, CopyOutlined, DeleteOutlined, FontColorsOutlined, CloseCircleOutlined, AntDesignOutlined } from '@ant-design/icons'
import asyncComponent from '@/utils/asyncComponent'
import asyncIconComponent from '@/utils/asyncIconComponent'
@@ -75,13 +75,12 @@
        connectDropTarget(<th {...restProps} index={index} style={style} onDoubleClick={() => this.props.editColumn(column)}>
          <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={
            <div className="mk-popover-control" onDoubleClick={(e) => e.stopPropagation()}>
              {['custom', 'colspan', 'action'].includes(column.type) ?
                <PlusOutlined className="plus" title="添加" onClick={() => this.props.addElement(column)} /> : null
              }
              {column.type === 'colspan' ? <PlusOutlined className="plus" title="添加列" onClick={() => this.props.addElement(column)} /> : null}
              {column.type === 'custom' ? <PlusOutlined className="plus" title="添加元素" onClick={() => this.props.addElement(column)} /> : null}
              {column.type === 'custom' ? <PlusSquareOutlined className="plus" title="添加按钮" onClick={() => this.props.addElement(column, 'button')} /> : null}
              <EditOutlined className="edit" title="编辑" onClick={() => this.props.editColumn(column)} />
              {column.type === 'custom' ? <PasteComponent options={['customCardElement']} updateConfig={(res, resolve) => this.props.pasteCell(column, res, resolve)} /> : null}
              {column.type === 'action' ? <PasteComponent options={['action']} updateConfig={(res, resolve) => this.props.pasteCell(column, res, resolve)} /> : null}
              {column.type === 'custom' || column.type === 'action' ? <FontColorsOutlined className="style" title="调整样式" onClick={() => this.props.changeStyle(column)}/> : null}
              {column.type === 'custom' ? <PasteComponent options={['customCardElement', 'action']} updateConfig={(res, resolve) => this.props.pasteCell(column, res, resolve)} /> : null}
              {column.type === 'custom' ? <FontColorsOutlined className="style" title="调整样式" onClick={() => this.props.changeStyle(column)}/> : null}
              <DeleteOutlined className="close" title="删除" onClick={this.deleteCol} />
              {['text', 'number', 'formula'].includes(column.type) ? <MarkColumn field={column.field || ''} columns={fields} marks={column.marks} onSubmit={this.updateMarks} /> : null }
            </div>
@@ -104,13 +103,13 @@
        <th {...restProps} style={style} key={column.uuid} onDoubleClick={() => this.props.editColumn(column)}>
          <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={
            <div className="mk-popover-control" onDoubleClick={(e) => e.stopPropagation()}>
              {['custom', 'colspan'].includes(column.type) ?
                <PlusOutlined className="plus" title="添加" onClick={() => this.props.addElement(column)} /> : null
              }
              {column.type === 'colspan' ? <PlusOutlined className="plus" title="添加列" onClick={() => this.props.addElement(column)} /> : null}
              {column.type === 'custom' ? <PlusOutlined className="plus" title="添加元素" onClick={() => this.props.addElement(column)} /> : null}
              {column.type === 'custom' ? <PlusSquareOutlined className="plus" title="添加按钮" onClick={() => this.props.addElement(column, 'button')} /> : null}
              <EditOutlined className="edit" title="编辑" onClick={() => this.props.editColumn(column)} />
              {column.type === 'custom' ? <PasteComponent options={['customCardElement']} updateConfig={(res, resolve) => this.props.pasteCell(column, res, resolve)} /> : null}
              {column.type === 'custom' ? <PasteComponent options={['customCardElement', 'action']} updateConfig={(res, resolve) => this.props.pasteCell(column, res, resolve)} /> : null}
              <DeleteOutlined className="close" title="删除" onClick={this.deleteCol} />
              {column && ['text', 'number', 'formula'].includes(column.type) ? <MarkColumn field={column.field || ''} columns={fields} marks={column.marks} onSubmit={this.updateMarks} /> : null }
              {['text', 'number', 'formula'].includes(column.type) ? <MarkColumn field={column.field || ''} columns={fields} marks={column.marks} onSubmit={this.updateMarks} /> : null }
            </div>
          } trigger="hover">
            {children}
@@ -177,12 +176,6 @@
    if (column && column.type === 'custom') {
      return (
        <td style={{padding: 0, ...(column.style || {})}} className={className}>
          <CardCellComponent cards={config} cardCell={column} elements={column.elements} updateElement={this.updateCard}/>
        </td>
      )
    } else if (column && column.type === 'action') {
      return (
        <td style={{padding: 0, textAlign: column.Align, ...(column.style || {})}} className={'action-column ' + className}>
          <CardCellComponent cards={config} cardCell={column} elements={column.elements} updateElement={this.updateCard}/>
        </td>
      )
@@ -301,15 +294,13 @@
    let _columns = fromJS(this.state.columns).toJS()
    let type = item.subType
    if (!['text', 'number', 'textarea', 'custom', 'action', 'formula', 'index', 'colspan'].includes(item.subType)) {
    if (!['text', 'number', 'textarea', 'custom', 'formula', 'index', 'colspan'].includes(item.subType)) {
      type = 'text'
    }
    let col = { focus: true, uuid: Utils.getuuid(), label: 'label', field: '', type: type, elements: [] }
    let col = { focus: true, uuid: Utils.getuuid(), Width: 120, label: 'label', field: '', type: type, elements: [] }
    if (col.type === 'colspan') {
      col.subcols = []
    } else if (col.type === 'action') {
      col.label = '操作'
    } else if (col.type === 'index') {
      col.label = '序号'
    }
@@ -364,14 +355,23 @@
  pasteCell = (col, cell, resolve) => {
    resolve({status: true})
    
    delete cell.copyType
    cell.uuid = Utils.getuuid()
    cell.focus = true
    if (!cell.eleType) {
      if (cell.copyType === 'action') {
        cell.eleType = 'button'
        cell.width = cell.width || 12
      } else {
        cell.eleType = 'text'
      }
    }
    delete cell.copyType
    
    MKEmitter.emit('cardAddElement', col.uuid, cell)
  }
  addElement = (col) => {
  addElement = (col, type) => {
    let column = fromJS(col).toJS()
    if (column.type === 'colspan') {
@@ -384,11 +384,7 @@
      })
      this.updateCol(column)
    } else if (column.type === 'custom') {
      let newcard = {uuid: Utils.getuuid(), focus: true, width: 24, eleType: 'text', datatype: 'dynamic', style: {paddingLeft: '4px'}}
      // 注册事件-添加元素
      MKEmitter.emit('cardAddElement', column.uuid, newcard)
    } else if (column.type === 'action') {
      if (type === 'button') {
      let newcard = {
        uuid: Utils.getuuid(),
        focus: true,
@@ -404,6 +400,12 @@
      // 注册事件-添加元素
      MKEmitter.emit('cardAddElement', column.uuid, newcard)
      } else {
        let newcard = {uuid: Utils.getuuid(), focus: true, width: 24, eleType: 'text', datatype: 'dynamic', style: {paddingLeft: '4px'}}
        // 注册事件-添加元素
        MKEmitter.emit('cardAddElement', column.uuid, newcard)
      }
    }
  }
@@ -419,9 +421,6 @@
    } else if (col.type === 'custom') {
      col.style = card.style || {}
      col.elements = card.type === 'custom' ? (card.elements || []) : []
    } else if (col.type === 'action') {
      col.style = card.style || {}
      col.elements = card.type === 'action' ? (card.elements || []) : []
    }
    window.GLOB.precolumnId = window.GLOB.columnId || ''
@@ -483,7 +482,22 @@
  deleteCol = (col) => {
    let _columns = fromJS(this.state.columns).toJS()
    if (col.type === 'colspan' && col.subcols && col.subcols.length > 0) {
      let Index = _columns.findIndex(item => item.uuid === col.uuid)
      if (Index !== -1) {
        let list = col.subcols.map(item => {
          item.isSub = false
          return item
        })
        _columns.splice(Index, 1, ...list)
      } else {
    _columns = this.loopDelCol(_columns, col)
      }
    } else {
      _columns = this.loopDelCol(_columns, col)
    }
    this.setState({
      columns: _columns
src/menu/components/table/edit-table/columns/index.scss
@@ -74,11 +74,6 @@
        }
      }
    }
    .action-column {
      .card-detail-row:empty {
        min-height: 40px;
      }
    }
    tr:hover td {
      background: #ffffff!important;
    }
src/menu/components/table/edit-table/columns/tableIn/customscript/index.jsx
@@ -47,19 +47,37 @@
  }
  edit = (record) => {
    const { type } = this.props
    this.setState({
      editItem: record
    })
    if (type === 'fullscreen') {
      this.props.form.setFieldsValue({
        sql: record.sql
      })
    } else {
    this.props.form.setFieldsValue({
      sql: record.sql,
      position: record.position || 'back'
    })
  }
  }
  handleConfirm = () => {
    const { type } = this.props
    const { editItem } = this.state
    // 表单提交时检查输入值是否正确
    this.props.form.validateFieldsAndScroll((err, values) => {
      if (type === 'fullscreen' && err) {
        notification.warning({
          top: 92,
          message: '请输入sql!',
          duration: 5
        })
        return
      }
      if (!err) {
        if (/^[\s\n]+$/.test(values.sql)) {
          notification.warning({
@@ -71,6 +89,10 @@
        }
        
        values.uuid = this.state.editItem ? this.state.editItem.uuid : ''
        if (type === 'fullscreen' && editItem) {
          values.status = editItem.status || 'true'
        }
        let _quot = values.sql.match(/'{1}/g)
        let _lparen = values.sql.match(/\({1}/g)
@@ -264,8 +286,8 @@
  }
  render() {
    const { systemScripts, btn } = this.props
    const { usefulfields } = this.state
    const { systemScripts, btn, type } = this.props
    const { usefulfields, editItem } = this.state
    const { getFieldDecorator } = this.props.form
    const formItemLayout = {
      labelCol: {
@@ -281,24 +303,24 @@
    return (
      <Form {...formItemLayout} className="verify-form" id="verify-excelin-custom-scripts">
        <Row gutter={24}>
          {btn.sheet ? <Col span={8}>
          {!type && btn.sheet ? <Col span={8}>
            <Form.Item label={'表名'} style={{whiteSpace: 'nowrap', margin: 0}}>
              {btn.sheet}
            </Form.Item>
          </Col> : null}
          <Col span={10}>
          {!type ? <Col span={10}>
            <Form.Item label={'报错字段'} style={{margin: 0, whiteSpace: 'nowrap'}}>
              ErrorCode(增加后缀NT表示数据不回滚,如ENT、NNT、FNT、NMNT), retmsg
            </Form.Item>
          </Col>
          {usefulfields ? <Col span={24} className="sqlfield">
          </Col> : null}
          {!type ? <Col span={24} className="sqlfield">
            <Form.Item label={'可用字段'}>
              <Tooltip mouseLeaveDelay={0.3} mouseEnterDelay={0.3} placement="top" title={'公共值,请按照@xxx@格式使用。'}><span style={{color: '#1890ff'}}>BID, ID, LoginUID, SessionUid, UserID, Appkey, time_id</span></Tooltip>,&nbsp;
              <Tooltip mouseLeaveDelay={0.3} mouseEnterDelay={0.3} placement="top" title={'系统变量,系统会定义变量并赋值。'}><span style={{color: '#fa8c16'}}>UserName, FullName, RoleID, mk_departmentcode, mk_organization, mk_user_type, mk_nation, mk_province, mk_city, mk_district, mk_address</span></Tooltip>,&nbsp;
              {usefulfields},data_type(注:jskey为主键值,新增时前端生成;data_type为操作类型,新增 - add、修改 - upt、删除 - del)
            </Form.Item>
          </Col> : null}
          <Col span={8} style={{whiteSpace: 'nowrap'}}>
          {!type ? <Col span={8} style={{whiteSpace: 'nowrap'}}>
            <Form.Item style={{marginBottom: 0}} label={
              <Tooltip placement="bottomLeft" title={'自定义脚本与默认sql位置关系。'}>
                <QuestionCircleOutlined className="mk-form-tip" />
@@ -315,8 +337,8 @@
                </Radio.Group>
              )}
            </Form.Item>
          </Col>
          <Col span={10}>
          </Col> : null}
          {!type ? <Col span={10}>
            <Form.Item style={{marginBottom: 0}} label={'快捷添加'}>
              <Select
                showSearch
@@ -337,10 +359,10 @@
                )}
              </Select>
            </Form.Item>
          </Col>
          </Col> : null}
          <Col span={6} className="add">
            <Button onClick={this.handleConfirm} loading={this.state.loading} className="mk-green" style={{marginBottom: 15, marginLeft: 40}}>
              保存
              {type === 'fullscreen' && !editItem ? '添加' : '保存'}
            </Button>
            <Button onClick={this.handleCancel} style={{marginBottom: 15, marginLeft: 10}}>
              取消
src/menu/components/table/edit-table/columns/tableIn/index.jsx
@@ -7,7 +7,7 @@
import Api from '@/api'
import Utils from '@/utils/utils.js'
import MKEmitter from '@/utils/events.js'
import UniqueForm from './uniqueform'
import CustomScript from './customscript'
import asyncComponent from '@/utils/asyncComponent'
@@ -17,6 +17,7 @@
const { confirm } = Modal
const { Paragraph } = Typography
const EditTable = asyncComponent(() => import('@/templates/zshare/editTable'))
const FullScripts = asyncComponent(() => import('@/templates/zshare/verifycard/fullScripts'))
class VerifyTableCard extends Component {
  static propTpyes = {
@@ -125,15 +126,13 @@
        dataIndex: 'position',
        width: '10%',
        render: (text, record) => {
          let _text = ''
          if (record.position === 'front') {
            _text = 'sql前'
          } else if (record.position === 'init') {
            _text = '初始化'
          if (record.position === 'init') {
            return <span style={{color: 'orange'}}>初始化</span>
          } else if (record.position === 'front') {
            return <span style={{color: '#26C281'}}>sql前</span>
          } else {
            _text = 'sql后'
            return <span style={{color: '#1890ff'}}>sql后</span>
          }
          return _text
        }
      },
      {
@@ -321,6 +320,8 @@
      values.uuid = Utils.getuuid()
      verify.scripts.push(values)
    }
    MKEmitter.emit('editLineId', values.uuid)
    this.setState({
      verify: verify
@@ -579,6 +580,23 @@
              {verify.scripts.length ? <span className="count-tip">{verify.scripts.length}</span> : null}
            </span>
          } key="scripts">
            <FullScripts
              verify={verify}
              getScriptsFullForm={() => this.scriptsFullForm}
              getScriptsForm={() => this.scriptsForm}
              handleStatus={this.handleStatus}
              handleDelete={this.handleDelete}
            >
              <CustomScript
                type="fullscreen"
                btn={verify}
                usefulfields={fields}
                scripts={verify.scripts}
                systemScripts={this.state.systemScripts}
                scriptsChange={this.scriptsChange}
                wrappedComponentRef={(inst) => this.scriptsFullForm = inst}
              />
            </FullScripts>
            <CustomScript
              btn={verify}
              usefulfields={fields}
src/menu/components/table/edit-table/columns/tableIn/index.scss
@@ -77,4 +77,12 @@
      z-index: 1;
    }
  }
  .full-scripts {
    position: absolute;
    right: 24px;
    top: 0px;
    font-size: 16px;
    color: #1890ff;
    z-index: 1;
  }
}
src/menu/components/table/edit-table/index.jsx
@@ -96,11 +96,6 @@
              cell.uuid = Utils.getuuid()
              return cell
            })
          } else if (col.type === 'action' && col.elements) {
            col.elements = col.elements.map(cell => {
              cell.uuid = Utils.getuuid()
              return cell
            })
          }
          return col
        })
@@ -220,7 +215,7 @@
  addColumns = () => {
    let card = fromJS(this.state.card).toJS()
    card.cols.push({ focus: true, uuid: Utils.getuuid(), label: 'label', field: '', type: 'text' })
    card.cols.push({ focus: true, Width: 120, uuid: Utils.getuuid(), label: 'label', field: '', type: 'text' })
    this.setState({card})
  }
src/menu/components/table/edit-table/options.jsx
@@ -274,13 +274,13 @@
      type: 'radio',
      field: 'permission',
      label: '权限验证',
      initval: wrap.permission || 'false',
      initval: wrap.permission || (!appType ? 'true' : 'false'),
      required: false,
      options: [
        {value: 'true', label: '启用'},
        {value: 'false', label: '禁用'},
      ],
      forbid: !appType || sessionStorage.getItem('editMenuType') === 'popview'
      forbid: sessionStorage.getItem('editMenuType') === 'popview'
    },
    // {
    //   type: 'radio',
src/menu/components/table/normal-table/columns/editColumn/formconfig.jsx
@@ -65,13 +65,6 @@
    text: '序号'
  }]
  if (!card.isSub) {
    options.push({
      value: 'action',
      text: '操作'
    })
  }
  if (!card.linkurl && (!card.linkmenu || card.linkmenu.length === 0)) {
    card.perspective = ''
  }
@@ -159,6 +152,18 @@
        value: 'false',
        text: '否'
      }]
    },
    {
      type: 'radio',
      key: 'eval',
      label: '解析',
      initVal: card.eval || 'false',
      tooltip: '当公式内容涉及计算时请选择“是”,当公式内容为字段拼接时请选择“否”。',
      required: false,
      options: [
        { value: 'true', text: '是' },
        { value: 'false', text: '否' }
      ]
    },
    {
      type: 'radio',
@@ -409,18 +414,6 @@
      options: [
        { value: 'blank', text: '新窗口' },
        { value: 'self', text: '当前窗口' }
      ]
    },
    {
      type: 'radio',
      key: 'eval',
      label: '解析',
      initVal: card.eval || 'false',
      tooltip: '当公式内容涉及计算时请选择“是”,当公式内容为字段拼接时请选择“否”。',
      required: false,
      options: [
        { value: 'true', text: '是' },
        { value: 'false', text: '否' }
      ]
    },
    {
src/menu/components/table/normal-table/columns/editColumn/index.jsx
@@ -25,7 +25,6 @@
class NormalTableColumn extends Component {
  static propTpyes = {
    visible: PropTypes.bool,
    column: PropTypes.object,
    fields: PropTypes.array,
    submitCol: PropTypes.func,  // 提交事件
@@ -36,6 +35,8 @@
    visible: false,
    formlist: null
  }
  record = null
  UNSAFE_componentWillReceiveProps (nextProps) {
    if (nextProps.column && !is(fromJS(this.props.column), fromJS(nextProps.column))) {
@@ -50,18 +51,16 @@
    })
    
    let formlist = getColumnForm(column, fields)
    let _options = fromJS(columnTypeOptions[column.type]).toJS()
    if (column.type === 'text' || column.type === 'number') {
      if (column.perspective === 'linkmenu') {
        _options.push('linkmenu', 'linkfields', 'open')
      } else if (column.perspective === 'linkurl') {
        _options.push('linkurl', 'linkfields', 'open')
      }
    }
    this.record = {}
    formlist.forEach(item => {
      this.record[item.key] = item.initVal
    })
    let _options = this.getOptions()
    this.setState({
      visible: true,
      type: column.type,
      formlist: formlist.map(item => {
        item.hidden = !_options.includes(item.key)
@@ -85,9 +84,29 @@
    }
  }
  getOptions = () => {
    let _options = fromJS(columnTypeOptions[this.record.type]).toJS()
    if (this.record.type === 'text' || this.record.type === 'number') {
      if (this.record.perspective === 'linkmenu') {
        _options.push('linkmenu', 'linkfields', 'open')
      } else if (this.record.perspective === 'linkurl') {
        _options.push('linkurl', 'linkfields', 'open')
      }
    }
    if (this.record.type === 'formula' && this.record.eval === 'true') {
      _options.push('decimal')
    }
    return _options
  }
  typeChange = (key, value, option) => {
    this.record[key] = value
    if (key === 'type') {
      let _options = fromJS(columnTypeOptions[value]).toJS()
      let _options = this.getOptions()
      let _field = ''
      if (value === 'formula') {
@@ -95,8 +114,12 @@
      }
      this.setState({
        type: value,
        formlist: this.state.formlist.map(item => {
          if (item.key === 'decimal' && value === 'formula') {
            this.record.decimal = ''
          }
          item.initVal = this.record[item.key]
          item.hidden = !_options.includes(item.key)
          return item
@@ -110,8 +133,6 @@
          this.props.form.setFieldsValue({Align: 'center'})
        } else if (value === 'formula' && _field) {
          this.props.form.setFieldsValue({formula: '@' + _field + '@'})
        } else if (value === 'action') {
          this.props.form.setFieldsValue({Align: 'center', label: '操作'})
        } else if (value === 'index') {
          this.props.form.setFieldsValue({label: '序号'})
        }
@@ -129,13 +150,18 @@
        values.type = 'text'
      }
      if (values.type !== this.state.type) {
      let _type = this.record.type
      this.record.type = values.type
      if (values.type !== _type) {
        values.perspective = ''
        let _options = fromJS(columnTypeOptions[values.type]).toJS()
        this.record.perspective = ''
        let _options = this.getOptions()
        this.setState({
          type: values.type,
          formlist: this.state.formlist.map(item => {
            item.initVal = this.record[item.key]
            item.hidden = !_options.includes(item.key)
            return item
@@ -148,21 +174,12 @@
      }
    } else if (key === 'format' && value === 'percent') {
      this.props.form.setFieldsValue({postfix: '%'})
    }
  }
  changeRadio = (key, value) => {
    if (key === 'perspective') {
      let _options = fromJS(columnTypeOptions[this.state.type]).toJS()
      if (value === 'linkmenu') {
        _options.push('linkmenu', 'linkfields', 'open')
      } else if (value === 'linkurl') {
        _options.push('linkurl', 'linkfields', 'open')
      }
    } else if (['perspective', 'eval'].includes(key)) {
      let _options = this.getOptions()
      this.setState({
        formlist: this.state.formlist.map(item => {
          item.initVal = this.record[item.key]
          item.hidden = !_options.includes(item.key)
          return item
@@ -279,14 +296,10 @@
                  }
                ]
              })(
                <Radio.Group onChange={(e) => {this.changeRadio(item.key, e.target.value)}}>
                  {
                    item.options.map(option => {
                      return (
                        <Radio key={option.value} value={option.value}>{option.text}</Radio>
                      )
                    })
                  }
                <Radio.Group onChange={(e) => {this.typeChange(item.key, e.target.value)}}>
                  {item.options.map(option => {
                    return (<Radio key={option.value} value={option.value}>{option.text}</Radio>)
                  })}
                </Radio.Group>
              )}
            </Form.Item>
@@ -406,9 +419,23 @@
  }
  handleSubmit = () => {
    const { fields } = this.props
    // 表单提交时检查输入值是否正确
    this.props.form.validateFieldsAndScroll((err, values) => {
      if (!err) {
        // eslint-disable-next-line
        if (values.type === 'formula' && values.eval !== 'false' && /^[\u4E00-\u9FA50-9a-zA-Z_\s@\+\-\*\/]*$/ig.test(values.formula) && /[\+\-\*\/]/ig.test(values.formula)) {
          let cols = []
          fields.forEach(col => {
            if (/^(Int|Decimal)/ig.test(col.datatype)) {
              cols.push({reg: new RegExp('@' + col.field + '@', 'ig'), value: `(@${col.field}@)`})
            }
          })
          cols.forEach(col => {
            values.formula = values.formula.replace(col.reg, col.value)
          })
        }
        this.setState({visible: false, formlist: null})
        this.props.submitCol(values)
      }
src/menu/components/table/normal-table/columns/index.jsx
@@ -3,7 +3,7 @@
import { is, fromJS } from 'immutable'
import { DndProvider, DragSource, DropTarget } from 'react-dnd'
import { Table, Popover, Modal, message, Typography } from 'antd'
import { PlusOutlined, FileSyncOutlined, EditOutlined, CopyOutlined, DeleteOutlined, FontColorsOutlined, CloseCircleOutlined, AntDesignOutlined } from '@ant-design/icons'
import { PlusOutlined, PlusSquareOutlined, FileSyncOutlined, EditOutlined, CopyOutlined, DeleteOutlined, FontColorsOutlined, CloseCircleOutlined, AntDesignOutlined } from '@ant-design/icons'
import asyncComponent from '@/utils/asyncComponent'
import asyncIconComponent from '@/utils/asyncIconComponent'
@@ -54,7 +54,7 @@
  render() {
    const { connectDragSource, connectDropTarget, moveCol, dropCol, addElement, updateCol, editColumn, pasteCell, changeStyle, deleteCol, index, column, align, fields, children, ...restProps } = this.props
    if (index !== undefined) {
    if (index !== undefined && column) {
      let style = {cursor: 'move', textAlign: align}
      if (column.Width) {
        style.width = column.Width
@@ -66,18 +66,17 @@
      }
      return connectDragSource(
        connectDropTarget(<th {...restProps} index={index} style={style} onDoubleClick={() => column && this.props.editColumn(column)}>
        connectDropTarget(<th {...restProps} index={index} style={style} onDoubleClick={() => this.props.editColumn(column)}>
          <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={
            <div className="mk-popover-control" onDoubleClick={(e) => e.stopPropagation()}>
              {column && ['custom', 'colspan', 'action'].includes(column.type) ?
                <PlusOutlined className="plus" title="添加" onClick={() => this.props.addElement(column)} /> : null
              }
              {column.type === 'colspan' ? <PlusOutlined className="plus" title="添加列" onClick={() => this.props.addElement(column)} /> : null}
              {column.type === 'custom' ? <PlusOutlined className="plus" title="添加元素" onClick={() => this.props.addElement(column)} /> : null}
              {column.type === 'custom' ? <PlusSquareOutlined className="plus" title="添加按钮" onClick={() => this.props.addElement(column, 'button')} /> : null}
              <EditOutlined className="edit" title="编辑" onClick={() => this.props.editColumn(column)} />
              {column && column.type === 'custom' ? <PasteComponent options={['customCardElement']} updateConfig={(res, resolve) => this.props.pasteCell(column, res, resolve)} /> : null}
              {column && column.type === 'action' ? <PasteComponent options={['action']} updateConfig={(res, resolve) => this.props.pasteCell(column, res, resolve)} /> : null}
              {column && (column.type === 'custom' || column.type === 'action') ? <FontColorsOutlined className="style" title="调整样式" onClick={() => this.props.changeStyle(column)}/> : null}
              {column.type === 'custom' ? <PasteComponent options={['customCardElement', 'action']} updateConfig={(res, resolve) => this.props.pasteCell(column, res, resolve)} /> : null}
              {column.type === 'custom' ? <FontColorsOutlined className="style" title="调整样式" onClick={() => this.props.changeStyle(column)}/> : null}
              <DeleteOutlined className="close" title="删除" onClick={this.deleteCol} />
              {column && ['text', 'number', 'formula'].includes(column.type) ? <MarkColumn field={column.field || ''} columns={fields} marks={column.marks} onSubmit={this.updateMarks} /> : null }
              {['text', 'number', 'formula'].includes(column.type) ? <MarkColumn field={column.field || ''} columns={fields} marks={column.marks} onSubmit={this.updateMarks} /> : null }
            </div>
          } trigger="hover">
            {children}
@@ -99,13 +98,13 @@
        <th {...restProps} style={style} key={column.uuid} onDoubleClick={() => this.props.editColumn(column)}>
          <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={
            <div className="mk-popover-control" onDoubleClick={(e) => e.stopPropagation()}>
              {column && ['custom', 'colspan'].includes(column.type) ?
                <PlusOutlined className="plus" title="添加" onClick={() => this.props.addElement(column)} /> : null
              }
              {column.type === 'colspan' ? <PlusOutlined className="plus" title="添加列" onClick={() => this.props.addElement(column)} /> : null}
              {column.type === 'custom' ? <PlusOutlined className="plus" title="添加元素" onClick={() => this.props.addElement(column)} /> : null}
              {column.type === 'custom' ? <PlusSquareOutlined className="plus" title="添加按钮" onClick={() => this.props.addElement(column, 'button')} /> : null}
              <EditOutlined className="edit" title="编辑" onClick={() => this.props.editColumn(column)} />
              {column.type === 'custom' ? <PasteComponent options={['customCardElement']} updateConfig={(res, resolve) => this.props.pasteCell(column, res, resolve)} /> : null}
              {column.type === 'custom' ? <PasteComponent options={['customCardElement', 'action']} updateConfig={(res, resolve) => this.props.pasteCell(column, res, resolve)} /> : null}
              <DeleteOutlined className="close" title="删除" onClick={this.deleteCol} />
              {column && ['text', 'number', 'formula'].includes(column.type) ? <MarkColumn field={column.field || ''} columns={fields} marks={column.marks} onSubmit={this.updateMarks} /> : null }
              {['text', 'number', 'formula'].includes(column.type) ? <MarkColumn field={column.field || ''} columns={fields} marks={column.marks} onSubmit={this.updateMarks} /> : null }
            </div>
          } trigger="hover">
            {children}
@@ -174,12 +173,6 @@
    if (column && column.type === 'custom') {
      return (
        <td style={{padding: 0, ...(column.style || {})}} className={className}>
          <CardCellComponent cards={config} cardCell={column} elements={column.elements} updateElement={this.updateCard}/>
        </td>
      )
    } else if (column && column.type === 'action') {
      return (
        <td style={{padding: 0, textAlign: column.Align, ...(column.style || {})}} className={'action-column ' + className}>
          <CardCellComponent cards={config} cardCell={column} elements={column.elements} updateElement={this.updateCard}/>
        </td>
      )
@@ -300,8 +293,6 @@
    let col = { focus: true, uuid: Utils.getuuid(), label: 'label', field: '', type: item.subType, elements: [] }
    if (col.type === 'colspan') {
      col.subcols = []
    } else if (col.type === 'action') {
      col.label = '操作'
    } else if (col.type === 'index') {
      col.label = '序号'
    }
@@ -355,18 +346,25 @@
  pasteCell = (col, cell, resolve) => {
    resolve({status: true})
    cell.uuid = Utils.getuuid()
    cell.focus = true
    if (!cell.eleType) {
    if (cell.copyType === 'action') {
      cell.eleType = 'button'
        cell.width = cell.width || 12
      } else {
        cell.eleType = 'text'
      }
    }
    delete cell.copyType
    cell.uuid = Utils.getuuid()
    cell.focus = true
    
    MKEmitter.emit('cardAddElement', col.uuid, cell)
  }
  addElement = (col) => {
  addElement = (col, type) => {
    let column = fromJS(col).toJS()
    if (column.type === 'colspan') {
@@ -379,11 +377,7 @@
      })
      this.updateCol(column)
    } else if (column.type === 'custom') {
      let newcard = {uuid: Utils.getuuid(), focus: true, width: 24, eleType: 'text', datatype: 'dynamic', style: {paddingLeft: '4px'}}
      // 注册事件-添加元素
      MKEmitter.emit('cardAddElement', column.uuid, newcard)
    } else if (column.type === 'action') {
      if (type === 'button') {
      let newcard = {
        uuid: Utils.getuuid(),
        focus: true,
@@ -399,6 +393,12 @@
      // 注册事件-添加元素
      MKEmitter.emit('cardAddElement', column.uuid, newcard)
      } else {
        let newcard = {uuid: Utils.getuuid(), focus: true, width: 24, eleType: 'text', datatype: 'dynamic', style: {paddingLeft: '4px'}}
        // 注册事件-添加元素
        MKEmitter.emit('cardAddElement', column.uuid, newcard)
      }
    }
  }
@@ -414,9 +414,6 @@
    } else if (col.type === 'custom') {
      col.style = card.style || {}
      col.elements = card.type === 'custom' ? (card.elements || []) : []
    } else if (col.type === 'action') {
      col.style = card.style || {}
      col.elements = card.type === 'action' ? (card.elements || []) : []
    }
    window.GLOB.precolumnId = window.GLOB.columnId || ''
src/menu/components/table/normal-table/columns/index.scss
@@ -62,11 +62,6 @@
        }
      }
    }
    .action-column {
      .card-detail-row:empty {
        min-height: 40px;
      }
    }
    tr:hover td {
      background: #ffffff!important;
    }
src/menu/components/table/normal-table/index.jsx
@@ -106,11 +106,6 @@
              cell.uuid = Utils.getuuid()
              return cell
            })
          } else if (col.type === 'action' && col.elements) {
            col.elements = col.elements.map(cell => {
              cell.uuid = Utils.getuuid()
              return cell
            })
          }
          return col
        })
@@ -324,8 +319,13 @@
    let _actions = [...action]
    cols.forEach(col => {
      if (col.type !== 'action') return
      _actions.push(...col.elements)
      if (col.type === 'custom') {
        col.elements.forEach(cell => {
          if (cell.eleType !== 'button') return
          _actions.push(cell)
        })
      }
    })
    return getWrapForm(wrap, _actions, columns)
src/menu/components/table/normal-table/options.jsx
@@ -269,13 +269,13 @@
      type: 'radio',
      field: 'permission',
      label: '权限验证',
      initval: wrap.permission || 'false',
      initval: wrap.permission || (!appType ? 'true' : 'false'),
      required: false,
      options: [
        {value: 'true', label: '启用'},
        {value: 'false', label: '禁用'},
      ],
      forbid: !appType || sessionStorage.getItem('editMenuType') === 'popview'
      forbid: sessionStorage.getItem('editMenuType') === 'popview'
    },
    {
      type: 'multiselect',
src/menu/components/timeline/normal-timeline/options.jsx
@@ -165,13 +165,13 @@
      type: 'radio',
      field: 'permission',
      label: '权限验证',
      initval: wrap.permission || 'false',
      initval: wrap.permission || (!appType ? 'true' : 'false'),
      required: false,
      options: [
        {value: 'true', label: '启用'},
        {value: 'false', label: '禁用'},
      ],
      forbid: !appType || sessionStorage.getItem('editMenuType') === 'popview'
      forbid: sessionStorage.getItem('editMenuType') === 'popview'
    },
    {
      type: 'radio',
src/menu/modulecell/index.jsx
@@ -100,8 +100,7 @@
          { subType: 'custom', text: '自定义列', type: 'col', $init: true },
          { subType: 'colspan', text: '合并列', type: 'col', $init: true },
          { subType: 'formula', text: '公式', type: 'col', $init: true },
          { subType: 'index', text: '序号', type: 'col', $init: true },
          { subType: 'action', text: '操作', type: 'col', $init: true }
          { subType: 'index', text: '序号', type: 'col', $init: true }
        ]
      }
    ]
src/menu/modulesource/option.jsx
@@ -30,6 +30,7 @@
import mindmap from '@/assets/mobimg/mindmap.png'
import indent from '@/assets/mobimg/indent.jfif'
import kapmap from '@/assets/mobimg/kapmap.jfif'
// import xflow from '@/assets/mobimg/xflow.png'
import Voucher from '@/assets/mobimg/voucher.png'
import Account from '@/assets/mobimg/account.png'
@@ -65,6 +66,7 @@
  { type: 'menu', url: mindmap, component: 'antvG6', subtype: 'mindmap', title: '思维导图', width: 24 },
  { type: 'menu', url: indent, component: 'antvG6', subtype: 'indentTree', title: '缩进文件树', width: 24 },
  { type: 'menu', url: kapmap, component: 'antvG6', subtype: 'kapmap', title: '知识图谱树', width: 24 },
  // { type: 'menu', url: xflow, component: 'antvX6', subtype: 'xflow', title: '流程图', width: 24 },
  { type: 'menu', url: chart, component: 'chart', subtype: 'custom', title: '自定义图表', width: 24, forbid: ['billPrint'] },
  { type: 'menu', url: Editor, component: 'editor', subtype: 'brafteditor', title: '富文本', width: 24 },
  { type: 'menu', url: SandBox, component: 'code', subtype: 'sandbox', title: '自定义', width: 24 },
src/menu/replaceField/index.jsx
@@ -358,8 +358,9 @@
          if (item.cols) {
            let _update = (cols) => {
              return cols.map(col => {
                if (col.type === 'action' && col.elements) {
                if (col.type === 'custom' && col.elements) {
                  col.elements = col.elements.map(m => {
                    if (m.eleType === 'button') {
                    if (m.modal && m.modal.fields) {
                      m.modal.fields = m.modal.fields.map(col => {
                        if (col.field && map[col.field.toLowerCase()]) {
@@ -379,13 +380,10 @@
                    if (m.config && m.config.components) {
                      m.config.components = _replace(m.config.components)
                    }
                    return m
                  })
                } else if (col.type === 'custom' && col.elements) {
                  col.elements = col.elements.map(m => {
                    } else {
                    if (m.datatype === 'dynamic' && map[m.field.toLowerCase()]) {
                      m.field = map[m.field.toLowerCase()].FieldName
                      }
                    }
                    return m
@@ -532,8 +530,9 @@
          if (item.cols) {
            let _update = (cols) => {
              return cols.map(col => {
                if (col.type === 'action' && col.elements) {
                if (col.type === 'custom' && col.elements) {
                  col.elements = col.elements.map(m => {
                    if (m.eleType === 'button') {
                    if (m.modal && m.modal.fields) {
                      m.modal.fields = m.modal.fields.map(col => {
                        if (col.field && map[col.field.toLowerCase()]) {
@@ -553,6 +552,7 @@
                    if (m.config && m.config.components) {
                      m.config.components = _replace(m.config.components)
                    }
                    }
                    return m
                  })
src/menu/transfer/index.jsx
@@ -85,7 +85,7 @@
          })
          tab.components[0].cols = tab.components[0].cols.filter(col => !(col.field && col.Hide === 'true'))
          tab.components[0].cols.forEach(col => {
            if (col.type !== 'action') return
            if (col.type !== 'custom') return
            col.elements.forEach(btn => {
              if (btn.OpenType === 'popview' && btn.config) {
                btn.config.Template = 'CustomPage'
@@ -111,7 +111,7 @@
        })
        item.cols = item.cols.filter(col => !(col.field && col.Hide === 'true'))
        item.cols.forEach(col => {
          if (col.type !== 'action') return
          if (col.type !== 'custom') return
          col.elements.forEach(btn => {
            if (btn.OpenType === 'popview' && btn.config) {
              btn.config.Template = 'CustomPage'
src/tabviews/basetable/index.jsx
@@ -316,6 +316,8 @@
            return false
          } else if (col.Hide === 'true') {
            return false
          } else if (col.type === 'action') {
            col.type = 'custom'
          }
          
          if (col.type === 'number') {
@@ -334,8 +336,39 @@
              return false
            }
          } else if (col.type === 'custom') {
            col.elements = col.elements.map(cell => {
              if (['text', 'number', 'formula'].includes(cell.eleType)) {
            col.elements = col.elements.filter(cell => {
              if (cell.eleType === 'button') {
                if (cell.hidden === 'true') return false
                cell.logLabel = item.$menuname + '-' + cell.label
                cell.Ot = cell.Ot || 'requiredSgl'
                cell.ContainerId = this.state.ContainerId
                cell.syncComponentId = cell.syncComponent ? (cell.syncComponent.pop() || '') : ''
                cell.$menuId = item.uuid
                cell.$MenuID = this.props.MenuID
                cell.$view = 'popview'
                if (cell.syncComponentId === item.setting.supModule) {
                  cell.syncComponentId = ''
                  if (cell.execSuccess === 'line' || cell.execSuccess === 'grid') {
                    cell.execSuccess = 'mainline'
                  }
                }
                if (cell.OpenType === 'funcbutton' && cell.funcType === 'print' && cell.verify) { // 打印机设置
                  cell = this.getPrinter(cell, item.uuid)
                }
                if (cell.controlField) {
                  if (/,/ig.test(cell.controlVal)) {
                    cell.controlVals = cell.controlVal.split(',')
                  } else {
                    cell.controlVals = [(cell.controlVal || '')]
                  }
                }
                return skip || permAction[cell.uuid]
              } else if (['text', 'number', 'formula'].includes(cell.eleType)) {
                if (!cell.height) {
                  cell.innerHeight = 'auto'
                }
@@ -346,8 +379,12 @@
                  }
                }
              }
              return cell
              return true
            })
            if (col.elements.length === 0) {
              return false
            }
          }
    
          if (col.linkmenu && col.linkmenu.length > 0) {
@@ -399,43 +436,6 @@
          return skip || permAction[cell.uuid]
        })
      }
      item.cols = item.cols.filter(col => {
        if (col.type !== 'action') return true
        col.elements = col.elements.filter(cell => {
          if (cell.hidden === 'true') return false
          cell.logLabel = item.$menuname + '-' + cell.label
          cell.Ot = cell.Ot || 'requiredSgl'
          cell.ContainerId = this.state.ContainerId
          cell.syncComponentId = cell.syncComponent ? (cell.syncComponent.pop() || '') : ''
          cell.$menuId = item.uuid
          cell.$MenuID = this.props.MenuID
          cell.$view = 'popview'
          if (cell.syncComponentId === item.setting.supModule) {
            cell.syncComponentId = ''
            if (cell.execSuccess === 'line' || cell.execSuccess === 'grid') {
              cell.execSuccess = 'mainline'
            }
          }
          if (cell.OpenType === 'funcbutton' && cell.funcType === 'print' && cell.verify) { // 打印机设置
            cell = this.getPrinter(cell, item.uuid)
          }
          if (cell.controlField) {
            if (/,/ig.test(cell.controlVal)) {
              cell.controlVals = cell.controlVal.split(',')
            } else {
              cell.controlVals = [(cell.controlVal || '')]
            }
          }
          return skip || permAction[cell.uuid]
        })
        return col.elements.length !== 0
      })
      
      return true
    })
src/tabviews/custom/components/card/cardcellList/index.jsx
@@ -76,10 +76,8 @@
    elements: PropTypes.array,       // 元素集
  }
  state = {}
  shouldComponentUpdate (nextProps, nextState) {
    return !is(fromJS(this.state), fromJS(nextState)) || !is(fromJS(this.props), fromJS(nextProps))
    return !is(fromJS(this.props), fromJS(nextProps))
  }
  /**
@@ -133,12 +131,7 @@
      }
      window.open(_url)
      return
    } else if (card.linkType === 'qywx') {
      notification.warning({
        top: 92,
        message: 'PC不支持打开企业微信!',
        duration: 5
      })
    } else if (card.linkType === 'qywx' || card.linkType === 'linkmenu') {
      return
    }
@@ -757,6 +750,10 @@
                // eslint-disable-next-line
                _val = eval(_val)
              } catch (e) {
                if (window.debugger) {
                  console.info(_val)
                  console.warn(e)
                }
                _val = 0
              }
            }
@@ -779,6 +776,10 @@
              // eslint-disable-next-line
              _val = eval(_val)
            } catch (e) {
              if (window.debugger) {
                console.info(_val)
                console.warn(e)
              }
              _val = ''
            }
          }
@@ -790,6 +791,11 @@
          return null
        }
  
        if (card.round && typeof(val) === 'number') {
          val = Math.round(val * card.round) / card.round
          val = val.toFixed(card.decimal)
        }
        if (val !== '') {
          if (val && typeof(val) === 'string') {
            val = val.replace(/\n/ig, '<br/>')
src/tabviews/custom/components/module/voucher/index.jsx
@@ -609,7 +609,7 @@
          sup_data.push(`'${n.uuid}','${item.subject_voucher_code || ''}','${item.voucher_lp || ''}','${n.voucher_sup_lp || ''}','${item.subject_code}','${item.subject_name}','${n.sup_voucher_text || ''}','${direct}',${item.debit || item.credit},'${n.customercode || ''}','${n.customername || ''}','${n.suppliercode || ''}','${n.suppliername || ''}','${n.co_pro_code || ''}','${n.co_pro_name || ''}','${n.workercode || ''}','${n.workername || ''}','${n.project_code || ''}','${n.project_name || ''}','${n.productcode || ''}','${n.productname || ''}','${n.cash_flow_code || ''}','${n.cash_flow_name || ''}','${n.sup_acc_code || ''}','${n.sup_acc_name || ''}','${n.sup_acc_type || ''}','${item.uuid}',0,'${n.lessor_code || ''}','${n.lessor_name || ''}','${n.logistics_code || ''}','${n.logistics_name || ''}'`)
        })
      }
      return `'${item.uuid}','${item.subject_voucher_code || ''}','${item.voucher_lp || ''}','${item.subject_code}','${item.subject_name}','${item.subject_voucher_text || ''}',${count ? item.fcc_count || 0 : 0},${count ? item.net_unitprice || 0 : 0},'${item.unit}',${item.debit || item.credit},'${direct}','${curr ? item.exratecode : '01010001'}','${curr ? item.exratename : 'CNY'}',${curr ? item.unitratio || 0 : 0},'${item.sup_accounting}',${item.debit ? 1 : -1},${curr ? item.foreign_amount || 0 : 0},0,'${item.local_currency || ''}','${count ? 'Y' : ''}','${curr ? 'Y' : ''}'`
      return `'${item.uuid}','${item.subject_voucher_code || ''}','${item.voucher_lp || ''}','${item.subject_code}','${item.subject_name}','${item.subject_voucher_text || ''}',${count ? item.fcc_count || 0 : 0},${count ? item.net_unitprice || 0 : 0},'${item.unit}',${item.debit || item.credit},'${direct}','${curr ? item.exratecode : '01010001'}','${curr ? item.exratename : 'CNY'}',${curr ? item.unitratio || 0 : 0},'${item.sup_accounting}',${item.debit ? 1 : -1},${curr ? item.foreign_amount || 0 : 0},0,'${item.local_currency || ''}','${count ? 'Y' : ''}','${curr ? 'Y' : ''}','${item.closing_foreign_exchange || ''}'`
    })
    if (type === 'createVoucher') {
@@ -625,7 +625,7 @@
      let curr = item.foreign_currency_type === 'Y'
      let direct = item.debit ? 'debit' : 'credit'
      subject_data.push(`'${item.uuid}','${item.subject_voucher_code || ''}','${item.voucher_lp || ''}','${item.subject_code}','${item.subject_name}','${item.subject_voucher_text || ''}',${count ? item.fcc_count || 0 : 0},${count ? item.net_unitprice || 0 : 0},'${item.unit}',${item.debit || item.credit},'${direct}','${curr ? item.exratecode : '01010001'}','${curr ? item.exratename : 'CNY'}',${curr ? item.unitratio || 0 : 0},'${item.sup_accounting}',${item.debit ? 1 : -1},${curr ? item.foreign_amount || 0 : 0},1,'${item.local_currency || ''}','${count ? 'Y' : ''}','${curr ? 'Y' : ''}'`)
      subject_data.push(`'${item.uuid}','${item.subject_voucher_code || ''}','${item.voucher_lp || ''}','${item.subject_code}','${item.subject_name}','${item.subject_voucher_text || ''}',${count ? item.fcc_count || 0 : 0},${count ? item.net_unitprice || 0 : 0},'${item.unit}',${item.debit || item.credit},'${direct}','${curr ? item.exratecode : '01010001'}','${curr ? item.exratename : 'CNY'}',${curr ? item.unitratio || 0 : 0},'${item.sup_accounting}',${item.debit ? 1 : -1},${curr ? item.foreign_amount || 0 : 0},1,'${item.local_currency || ''}','${count ? 'Y' : ''}','${curr ? 'Y' : ''}','${item.closing_foreign_exchange || ''}'`)
    })
    supMap.forEach(n => {
@@ -893,7 +893,7 @@
          sup_data.push(`'${n.uuid}','${item.subject_voucher_code || ''}','${item.voucher_lp || ''}','${n.voucher_sup_lp || ''}','${item.subject_code}','${item.subject_name}','${n.sup_voucher_text || ''}','${direct}',${item.debit || item.credit || 0},'${n.customercode || ''}','${n.customername || ''}','${n.suppliercode || ''}','${n.suppliername || ''}','${n.co_pro_code || ''}','${n.co_pro_name || ''}','${n.workercode || ''}','${n.workername || ''}','${n.project_code || ''}','${n.project_name || ''}','${n.productcode || ''}','${n.productname || ''}','${n.cash_flow_code || ''}','${n.cash_flow_name || ''}','${n.sup_acc_code || ''}','${n.sup_acc_name || ''}','${n.sup_acc_type || ''}','${item.uuid}',0,'${n.lessor_code || ''}','${n.lessor_name || ''}','${n.logistics_code || ''}','${n.logistics_name || ''}'`)
        })
      }
      return `'${item.uuid}','${item.subject_voucher_code || ''}','${item.voucher_lp || ''}','${item.subject_code}','${item.subject_name}','${item.subject_voucher_text || ''}',${count ? item.fcc_count || 0 : 0},${count ? item.net_unitprice || 0 : 0},'${item.unit}',${item.debit || item.credit || 0},'${direct}','${curr ? item.exratecode : '01010001'}','${curr ? item.exratename : 'CNY'}',${curr ? item.unitratio || 0 : 0},'${item.sup_accounting}',${item.direct ? 1 : -1},${curr ? item.foreign_amount || 0 : 0},0,'${item.local_currency || ''}','${count ? 'Y' : ''}','${curr ? 'Y' : ''}'`
      return `'${item.uuid}','${item.subject_voucher_code || ''}','${item.voucher_lp || ''}','${item.subject_code}','${item.subject_name}','${item.subject_voucher_text || ''}',${count ? item.fcc_count || 0 : 0},${count ? item.net_unitprice || 0 : 0},'${item.unit}',${item.debit || item.credit || 0},'${direct}','${curr ? item.exratecode : '01010001'}','${curr ? item.exratename : 'CNY'}',${curr ? item.unitratio || 0 : 0},'${item.sup_accounting}',${item.direct ? 1 : -1},${curr ? item.foreign_amount || 0 : 0},0,'${item.local_currency || ''}','${count ? 'Y' : ''}','${curr ? 'Y' : ''}','${item.closing_foreign_exchange || ''}'`
    })
    voucherMap.forEach(item => {
@@ -901,7 +901,7 @@
      let curr = item.foreign_currency_type === 'Y'
      let direct = !item.credit ? 'debit' : 'credit'
      subject_data.push(`'${item.uuid}','${item.subject_voucher_code || ''}','${item.voucher_lp || ''}','${item.subject_code}','${item.subject_name}','${item.subject_voucher_text || ''}',${count ? item.fcc_count || 0 : 0},${count ? item.net_unitprice || 0 : 0},'${item.unit}',${item.debit || item.credit || 0},'${direct}','${curr ? item.exratecode : '01010001'}','${curr ? item.exratename : 'CNY'}',${curr ? item.unitratio || 0 : 0},'${item.sup_accounting}',${item.direct ? 1 : -1},${curr ? item.foreign_amount || 0 : 0},1,'${item.local_currency || ''}','${count ? 'Y' : ''}','${curr ? 'Y' : ''}'`)
      subject_data.push(`'${item.uuid}','${item.subject_voucher_code || ''}','${item.voucher_lp || ''}','${item.subject_code}','${item.subject_name}','${item.subject_voucher_text || ''}',${count ? item.fcc_count || 0 : 0},${count ? item.net_unitprice || 0 : 0},'${item.unit}',${item.debit || item.credit || 0},'${direct}','${curr ? item.exratecode : '01010001'}','${curr ? item.exratename : 'CNY'}',${curr ? item.unitratio || 0 : 0},'${item.sup_accounting}',${item.direct ? 1 : -1},${curr ? item.foreign_amount || 0 : 0},1,'${item.local_currency || ''}','${count ? 'Y' : ''}','${curr ? 'Y' : ''}','${item.closing_foreign_exchange || ''}'`)
    })
    supMap.forEach(n => {
src/tabviews/custom/components/module/voucher/voucherTable/index.scss
@@ -31,10 +31,10 @@
      border-right: 1px solid #e9e9e9;
    }
    span:nth-child(3), span:nth-child(6) {
      border-color: #91d5ff;
      border-color: #474069;
    }
    span:nth-child(9) {
      border-color: #ffa39e;
      border-color: #C48584;
    }
  }
@@ -45,7 +45,7 @@
      tr {
        th {
          position: relative;
          background-color: transparent;
          background-color: #E3E7F2;
          padding: 0;
          height: 60px;
          line-height: 60px;
@@ -83,6 +83,9 @@
      max-width: 60px;
    }
    .ant-table-tbody {
      tr:last-child {
        background-color: #FBF8EF;
      }
      tr td {
        position: relative;
        background-color: transparent;
src/tabviews/custom/components/share/normalTable/index.jsx
@@ -340,7 +340,16 @@
          // eslint-disable-next-line
          content = eval(content)
        } catch (e) {
          if (window.debugger) {
            console.info(content)
            console.warn(e)
          }
          content = ''
        }
        if (col.round && typeof(content) === 'number') {
          content = Math.round(content * col.round) / col.round
          content = content.toFixed(col.decimal)
        }
      }
@@ -375,14 +384,6 @@
        style = {...style, ...col.style}
      }
      resProps.children = (
        <CardCellComponent data={record} cards={config} elements={col.elements}/>
      )
    } else if (col.type === 'action') {
      style.padding = '0px'
      if (col.style) {
        style = {...style, ...col.style}
      }
      resProps.children = (
        <CardCellComponent data={record} cards={config} elements={col.elements}/>
      )
@@ -477,7 +478,7 @@
              onCell: record => ({
                record,
                col: item,
                config: item.type === 'custom' || item.type === 'action' ? {setting, columns: fields} : null,
                config: item.type === 'custom' ? {setting, columns: fields} : null,
                triggerLink: this.triggerLink
              })
            }
src/tabviews/custom/components/table/edit-table/index.jsx
@@ -92,8 +92,9 @@
          if (item.subcols.length === 0) {
            return false
          }
        } else if (item.type === 'action') {
        } else if (item.type === 'custom') {
          item.elements.forEach(btn => {
            if (btn.eleType !== 'button') return
            if (btn.funcType === 'addline') {
              setting.addable = true
            }
@@ -480,7 +481,9 @@
        BID: id,
        BData: data
      }, () => {
        setTimeout(() => {
        this.loadmaindata(true, 'true')
        }, setting.delay || 0)
      })
    }
  }
src/tabviews/custom/components/table/edit-table/normalTable/index.jsx
@@ -220,15 +220,7 @@
      }
    }, 50)
    let values = {}
    // if (col.editField) {
    //   values[col.field] = label
    //   values[col.editField] = val
    // } else {
      values[col.field] = val
    // }
    MKEmitter.emit('changeRecord', col.tableId, {...record, ...values})
    MKEmitter.emit('changeRecord', col.tableId, {...record, [col.field]: val})
  }
  onSelectChange = (val, option) => {
@@ -244,12 +236,7 @@
        })
      }
      // if (col.editField) {
      //   values[col.field] = _option.label
      //   values[col.editField] = val
      // } else {
        values[col.field] = val
      // }
    }
    this.setState({editing: false})
@@ -333,22 +320,14 @@
              <Input className={err ? 'has-error' : ''} title={err} id={col.uuid + record.$$uuid} defaultValue={value} onChange={(e) => this.onChange(e.target.value)} onPressEnter={this.enterPress} onBlur={this.onBlur}/>
            </td>)
          } else if (col.editType === 'switch') {
            let _value = ''
            // if (col.editField) {
            //   _value = record[col.editField] !== undefined ? record[col.editField] : ''
            // } else {
              _value = record[col.field] !== undefined ? record[col.field] : ''
            // }
            let _value = record[col.field] !== undefined ? record[col.field] : ''
            return (<td className="editing_table_cell">
              <CusSwitch config={col} defaultValue={_value} autoFocus={true} onChange={this.onSwitchChange} onBlur={this.switchBlur}/>
            </td>)
          } else {
            let _value = ''
            // if (col.editField) {
            //   _value = record[col.editField] !== undefined ? record[col.editField] : ''
            // } else {
              _value = record[col.field] !== undefined ? record[col.field] : ''
            // }
            let _value = record[col.field] !== undefined ? record[col.field] : ''
            return (<td className="editing_table_cell">
              <Select
                showSearch
@@ -429,7 +408,7 @@
            val = ''
          }
          return (<td className="editing_table_cell">
            <InputNumber className={err ? 'has-error' : ''} title={err} id={col.uuid + record.$$uuid} defaultValue={val} onChange={(val) => this.onChange(val)} onPressEnter={this.enterPress} onBlur={this.onBlur}/>
            <InputNumber className={err ? 'has-error' : ''} precision={col.decimal || 0} title={err} id={col.uuid + record.$$uuid} defaultValue={val} onChange={(val) => this.onChange(val)} onPressEnter={this.enterPress} onBlur={this.onBlur}/>
          </td>)
        } else {
          return (<td className={className + ' pointer'} style={style}>
@@ -466,6 +445,10 @@
          // eslint-disable-next-line
          content = eval(content)
        } catch (e) {
          if (window.debugger) {
            console.info(content)
            console.warn(e)
          }
          content = ''
        }
      }
@@ -474,6 +457,11 @@
      if (col.noValue === 'hide' && content === 0) {
        content = ''
      }
      if (col.round && typeof(content) === 'number') {
        content = Math.round(content * col.round) / col.round
        content = content.toFixed(col.decimal)
      }
      if (content !== '') {
@@ -505,14 +493,6 @@
        style = {...style, ...col.style}
      }
      children = (
        <CardCellComponent data={record} cards={config} elements={col.elements}/>
      )
    } else if (col.type === 'action') {
      style.padding = '0px'
      if (col.style) {
        style = {...style, ...col.style}
      }
      children = (
        <CardCellComponent data={record} cards={config} elements={col.elements}/>
      )
@@ -640,15 +620,7 @@
      }
    }, 50)
    let values = {}
    // if (col.editField) {
    //   values[col.field] = label
    //   values[col.editField] = val
    // } else {
      values[col.field] = val
    // }
    MKEmitter.emit('changeRecord', col.tableId, {...record, ...values})
    MKEmitter.emit('changeRecord', col.tableId, {...record, [col.field]: val})
  }
  onSelectChange = (val, option) => {
@@ -664,12 +636,7 @@
        })
      }
      // if (col.editField) {
      //   values[col.field] = _option.label
      //   values[col.editField] = val
      // } else {
        values[col.field] = val
      // }
    }
    setTimeout(() => {
@@ -706,12 +673,7 @@
    let children = null
    if (col.type === 'text') {
      if (col.editable === 'true' && !disabled) {
        let _value = ''
        // if (col.editField) {
        //   _value = record[col.editField] !== undefined ? record[col.editField] : ''
        // } else {
          _value = record[col.field] !== undefined ? record[col.field] : ''
        // }
        let _value = record[col.field] !== undefined ? record[col.field] : ''
        
        if (!col.editType || col.editType === 'text') {
          children = (<>
@@ -775,6 +737,11 @@
            content = <span style={mark.innerStyle}>{content}</span>
          }
        }
        if (col.editable === 'true' && disabled) {
          content = <span style={{display: 'inline-block', padding: '0 6px'}}>{content}</span>
        }
        children = content
      }
    } else if (col.type === 'number') {
@@ -786,7 +753,7 @@
        }
        children = (<>
          <InputNumber className={err ? 'has-error' : ''} title={err} id={col.uuid + record.$$uuid} defaultValue={_value} onChange={(val) => this.onChange(val)} onPressEnter={this.enterPress} onBlur={this.onBlur}/>
          <InputNumber className={err ? 'has-error' : ''} title={err} precision={col.decimal || 0} id={col.uuid + record.$$uuid} defaultValue={_value} onChange={(val) => this.onChange(val)} onPressEnter={this.enterPress} onBlur={this.onBlur}/>
        </>)
      } else {
        let content = ''
@@ -837,6 +804,11 @@
            content = <span style={mark.innerStyle}>{content}</span>
          }
        }
        if (col.editable === 'true' && disabled) {
          content = <span style={{display: 'inline-block', padding: '0 6px'}}>{content}</span>
        }
        children = content
      }
    } else if (col.type === 'textarea') {
@@ -866,6 +838,10 @@
          // eslint-disable-next-line
          content = eval(content)
        } catch (e) {
          if (window.debugger) {
            console.info(content)
            console.warn(e)
          }
          content = ''
        }
      }
@@ -874,6 +850,11 @@
      if (col.noValue === 'hide' && content === 0) {
        content = ''
      }
      if (col.round && typeof(content) === 'number') {
        content = Math.round(content * col.round) / col.round
        content = content.toFixed(col.decimal)
      }
      if (content !== '') {
@@ -905,14 +886,6 @@
        style = {...style, ...col.style}
      }
      children = (
        <CardCellComponent data={record} cards={config} elements={col.elements}/>
      )
    } else if (col.type === 'action') {
      style.padding = '0px'
      if (col.style) {
        style = {...style, ...col.style}
      }
      children = (
        <CardCellComponent data={record} cards={config} elements={col.elements}/>
      )
@@ -1010,7 +983,7 @@
            onCell: record => ({
              record,
              col: item,
              config: item.type === 'custom' || item.type === 'action' ? {setting, columns: fields} : null,
              config: item.type === 'custom' ? {setting, columns: fields} : null,
            })
          }
        }
@@ -1109,7 +1082,13 @@
    if (menuid !== MenuID) return
    if (type !== 'line') {
      if (setting.editType === 'multi' && data.length > 0) {
        this.setState({edData: []}, () => {
      this.setState({edData: data})
        })
      } else {
        this.setState({edData: data})
      }
      if (setting.addable && data.length === 0) {
        setTimeout(() => {
src/tabviews/custom/index.jsx
@@ -473,53 +473,6 @@
        item.search = Utils.initSearchVal(item.search)
      }
      if (item.type === 'table') {
        let statFields = []
        let getCols = (cols) => {
          return cols.filter(col => {
            if (col.blacklist && col.blacklist.filter(v => roleId.indexOf(v) > -1).length > 0) {
              return false
            } else if (col.Hide === 'true') {
              return false
            }
            if (col.type === 'number') {
              if (col.sum === 'true' && !statFields.includes(col.field)) {
                statFields.push(col)
              }
              if (typeof(col.decimal) === 'number') {
                col.round = Math.pow(10, col.decimal)
                if (col.format === 'percent') {
                  col.decimal = col.decimal > 2 ? col.decimal - 2 : 0
                }
              }
            } else if (col.type === 'colspan') {
              col.subcols = getCols(col.subcols || [])
              if (col.subcols.length === 0) {
                return false
              }
            } else if (col.type === 'custom') {
              col.elements = col.elements.map(cell => {
                cell = this.resetElement(cell)
                return cell
              })
            }
            if (col.linkmenu && col.linkmenu.length > 0) {
              let menu_id = col.linkmenu.pop()
              col.linkThdMenu = window.GLOB.mkThdMenus.filter(m => m.MenuID === menu_id)[0] || ''
            } else {
              col.linkThdMenu = ''
            }
            return true
          })
        }
        item.cols = getCols(item.cols)
        item.statFields = statFields
      }
      let mutil = false
      if (item.wrap && item.wrap.supType === 'multi') { // 数据卡多上级组件
        mutil = true
@@ -531,6 +484,12 @@
        } else {
          item.setting.supModule = ''
        }
      }
      let pass = skip
      if (item.wrap && item.wrap.permission === 'false') {
        pass = true
      }
      // 权限过滤
@@ -553,11 +512,90 @@
            cell = this.getPrinter(cell, item.uuid)
          }
          return skip || permAction[cell.uuid]
          return pass || permAction[cell.uuid]
        })
      }
      if (item.type === 'card' || item.type === 'carousel' || item.type === 'timeline') {
      if (item.type === 'table') {
        let statFields = []
        let getCols = (cols) => {
          return cols.filter(col => {
            if (col.blacklist && col.blacklist.filter(v => roleId.indexOf(v) > -1).length > 0) {
              return false
            } else if (col.Hide === 'true') {
              return false
            } else if (col.type === 'action') {
              col.type = 'custom'
            }
            if (col.type === 'number') {
              if (col.sum === 'true' && !statFields.includes(col.field)) {
                statFields.push(col)
              }
              if (typeof(col.decimal) === 'number') {
                col.round = Math.pow(10, col.decimal)
                if (col.format === 'percent') {
                  col.decimal = col.decimal > 2 ? col.decimal - 2 : 0
                }
              }
            } else if (col.type === 'formula') {
              if (typeof(col.decimal) === 'number') {
                col.round = Math.pow(10, col.decimal)
              }
            } else if (col.type === 'colspan') {
              col.subcols = getCols(col.subcols || [])
              if (col.subcols.length === 0) {
                return false
              }
            } else if (col.type === 'custom') {
              col.elements = col.elements.filter(cell => {
                if (cell.eleType === 'button') {
                  if (cell.hidden === 'true') return false
                  cell = this.resetButton(item, cell, popview)
                  if (cell.syncComponentId === item.setting.supModule) {
                    cell.syncComponentId = ''
                    if (cell.execSuccess === 'line' || cell.execSuccess === 'grid') {
                      cell.execSuccess = 'mainline'
                    }
                  }
                  if (cell.OpenType === 'funcbutton' && cell.funcType === 'print' && cell.verify) { // 打印机设置
                    cell = this.getPrinter(cell, item.uuid)
                  }
                  return pass || permAction[cell.uuid]
                } else {
                  cell = this.resetElement(cell)
                }
                return true
              })
              if (col.elements.length === 0) {
                return false
              }
            }
            if (col.linkmenu && col.linkmenu.length > 0) {
              let menu_id = col.linkmenu.pop()
              col.linkThdMenu = window.GLOB.mkThdMenus.filter(m => m.MenuID === menu_id)[0] || ''
            } else {
              col.linkThdMenu = ''
            }
            return true
          })
        }
        item.cols = getCols(item.cols)
        item.statFields = statFields
        if (item.subtype === 'editable') {
          item.submit.logLabel = item.$menuname + '-提交'
          item.submit.$menuId = item.uuid
        }
      } else if (item.type === 'card' || item.type === 'carousel' || item.type === 'timeline') {
        item.subcards && item.subcards.forEach(card => {
          if (card.style.boxShadow) {
            delete card.style.hShadow
@@ -586,7 +624,7 @@
              cell = this.resetElement(cell)
            }
            return cell.eleType !== 'button' || skip || permAction[cell.uuid]
            return cell.eleType !== 'button' || pass || permAction[cell.uuid]
          })
          if (!card.backElements || card.backElements.length === 0) return
@@ -611,7 +649,7 @@
              cell = this.resetElement(cell)
            }
            return cell.eleType !== 'button' || skip || permAction[cell.uuid]
            return cell.eleType !== 'button' || pass || permAction[cell.uuid]
          })
        })
      } else if (item.type === 'balcony') {
@@ -642,36 +680,8 @@
            cell = this.resetElement(cell)
          }
          return cell.eleType !== 'button' || skip || permAction[cell.uuid]
          return cell.eleType !== 'button' || pass || permAction[cell.uuid]
        })
      } else if (item.type === 'table') {
        item.cols = item.cols.filter(col => {
          if (col.type !== 'action') return true
          col.elements = col.elements.filter(cell => {
            if (cell.hidden === 'true') return false
            cell = this.resetButton(item, cell, popview)
            if (cell.syncComponentId === item.setting.supModule) {
              cell.syncComponentId = ''
              if (cell.execSuccess === 'line' || cell.execSuccess === 'grid') {
                cell.execSuccess = 'mainline'
              }
            }
            if (cell.OpenType === 'funcbutton' && cell.funcType === 'print' && cell.verify) { // 打印机设置
              cell = this.getPrinter(cell, item.uuid)
            }
            return skip || permAction[cell.uuid]
          })
          return col.elements.length !== 0
        })
        if (item.subtype === 'editable') {
          item.submit.logLabel = item.$menuname + '-提交'
          item.submit.$menuId = item.uuid
        }
      } else if (item.type === 'form') {
        item.subcards = item.subcards.map(group => {
          group.subButton.uuid = group.uuid
@@ -805,6 +815,8 @@
        if (cell.format === 'percent') {
          cell.decimal = cell.decimal > 2 ? cell.decimal - 2 : 0
        }
      } else if (cell.eleType === 'formula' && typeof(cell.decimal) === 'number') {
        cell.round = Math.pow(10, cell.decimal)
      }
    } else if (cell.eleType === 'icon') {
      if (!cell.innerHeight) { // 兼容
src/tabviews/custom/popview/index.jsx
@@ -302,53 +302,6 @@
        item.search = Utils.initSearchVal(item.search)
      }
      if (item.type === 'table') {
        let statFields = []
        let getCols = (cols) => {
          return cols.filter(col => {
            if (col.blacklist && col.blacklist.filter(v => roleId.indexOf(v) > -1).length > 0) {
              return false
            } else if (col.Hide === 'true') {
              return false
            }
            if (col.type === 'number') {
              if (col.sum === 'true' && !statFields.includes(col.field)) {
                statFields.push(col)
              }
              if (typeof(col.decimal) === 'number') {
                col.round = Math.pow(10, col.decimal)
                if (col.format === 'percent') {
                  col.decimal = col.decimal > 2 ? col.decimal - 2 : 0
                }
              }
            } else if (col.type === 'colspan') {
              col.subcols = getCols(col.subcols || [])
              if (col.subcols.length === 0) {
                return false
              }
            } else if (col.type === 'custom') {
              col.elements = col.elements.map(cell => {
                cell = this.resetElement(cell)
                return cell
              })
            }
            if (col.linkmenu && col.linkmenu.length > 0) {
              let menu_id = col.linkmenu.pop()
              col.linkThdMenu = window.GLOB.mkThdMenus.filter(m => m.MenuID === menu_id)[0] || ''
            } else {
              col.linkThdMenu = ''
            }
            return true
          })
        }
        item.cols = getCols(item.cols)
        item.statFields = statFields
      }
      let mutil = false
      if (item.wrap && item.wrap.supType === 'multi') { // 数据卡多上级组件
        mutil = true
@@ -381,7 +334,81 @@
        })
      }
      if (item.type === 'card' || item.type === 'carousel' || item.type === 'timeline') {
      if (item.type === 'table') {
        let statFields = []
        let getCols = (cols) => {
          return cols.filter(col => {
            if (col.blacklist && col.blacklist.filter(v => roleId.indexOf(v) > -1).length > 0) {
              return false
            } else if (col.Hide === 'true') {
              return false
            } else if (col.type === 'action') {
              col.type = 'custom'
            }
            if (col.type === 'number') {
              if (col.sum === 'true' && !statFields.includes(col.field)) {
                statFields.push(col)
              }
              if (typeof(col.decimal) === 'number') {
                col.round = Math.pow(10, col.decimal)
                if (col.format === 'percent') {
                  col.decimal = col.decimal > 2 ? col.decimal - 2 : 0
                }
              }
            } else if (col.type === 'formula') {
              if (typeof(col.decimal) === 'number') {
                col.round = Math.pow(10, col.decimal)
              }
            } else if (col.type === 'colspan') {
              col.subcols = getCols(col.subcols || [])
              if (col.subcols.length === 0) {
                return false
              }
            } else if (col.type === 'custom') {
              col.elements = col.elements.filter(cell => {
                if (cell.eleType === 'button') {
                  if (cell.hidden === 'true' || cell.OpenType === 'popview') return false
                  cell = this.resetButton(item, cell, Tab)
                  if (cell.syncComponentId === item.setting.supModule) {
                    cell.syncComponentId = ''
                    if (cell.execSuccess === 'line' || cell.execSuccess === 'grid') {
                      cell.execSuccess = 'mainline'
                    }
                  }
                } else {
                  cell = this.resetElement(cell)
                }
                return true
              })
              if (col.elements.length === 0) {
                return false
              }
            }
            if (col.linkmenu && col.linkmenu.length > 0) {
              let menu_id = col.linkmenu.pop()
              col.linkThdMenu = window.GLOB.mkThdMenus.filter(m => m.MenuID === menu_id)[0] || ''
            } else {
              col.linkThdMenu = ''
            }
            return true
          })
        }
        item.cols = getCols(item.cols)
        item.statFields = statFields
        if (item.subtype === 'editable') {
          item.submit.logLabel = item.$menuname + '-提交'
          item.submit.$menuId = item.uuid
        }
      } else if (item.type === 'card' || item.type === 'carousel' || item.type === 'timeline') {
        item.subcards && item.subcards.forEach(card => {
          if (card.style.boxShadow) {
            delete card.style.hShadow
@@ -456,30 +483,6 @@
          return true
        })
      } else if (item.type === 'table') {
        item.cols = item.cols.filter(col => {
          if (col.type !== 'action') return true
          col.elements = col.elements.filter(cell => {
            if (cell.hidden === 'true' || cell.OpenType === 'popview') return false
            cell = this.resetButton(item, cell, Tab)
            if (cell.syncComponentId === item.setting.supModule) {
              cell.syncComponentId = ''
              if (cell.execSuccess === 'line' || cell.execSuccess === 'grid') {
                cell.execSuccess = 'mainline'
              }
            }
            return true
          })
          return col.elements.length !== 0
        })
        if (item.subtype === 'editable') {
          item.submit.logLabel = item.$menuname + '-提交'
          item.submit.$menuId = item.uuid
        }
      } else if (item.type === 'form') {
        item.subcards = item.subcards.map(group => {
          group.subButton.uuid = group.uuid
@@ -605,6 +608,8 @@
        if (cell.format === 'percent') {
          cell.decimal = cell.decimal > 2 ? cell.decimal - 2 : 0
        }
      } else if (cell.type === 'formula' && typeof(cell.decimal) === 'number') {
        cell.round = Math.pow(10, cell.decimal)
      }
    } else if (cell.eleType === 'icon') {
      if (!cell.innerHeight) { // 兼容
src/tabviews/zshare/actionList/normalbutton/index.jsx
@@ -868,7 +868,11 @@
          if (/'/.test(val)) {
            val = val.replace(/'/ig, '"')
          }
          if (form.isconst) {
            _initFormfields.push(`@${_key}=N'${val}'`)
          } else {
          _initFormfields.push(`@${_key}='${val}'`)
          }
        }
      }
      
@@ -2101,7 +2105,18 @@
      this.sendMessage(btn.verify, id)
    }
    if (btn.verify.wxNote === 'true') {
      if (btn.verify.wxTemplateId === 'mk_category_temp') {
        let verify = fromJS(btn.verify).toJS()
        verify.wxTemplateId = verify.wxCustomTempId
        verify.wxNoteKeys = verify.wxNoteKeys.filter(item => item.key)
        if (!verify.wxTemplateId || verify.wxNoteKeys.length === 0) return
        this.sendWxMessage(verify, id)
      } else {
      this.sendWxMessage(btn.verify, id)
      }
    }
  }
@@ -2124,8 +2139,15 @@
    param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
    param.secretkey = Utils.encrypt(param.LText, param.timestamp)
    let domain1 = ''
    let domain2 = ''
    if (['8IFltwzyKcu15iA8fqSyb6m-pMa88a3ZTu0No3vDHgo', 'LOB-bbt9jVncGh7IOAUdESh1Sgzcbt62UwOqSqcK9ok'].includes(verify.wxTemplateId) && options.sysType !== 'cloud') {
      domain1 = 'https://cloud.mk9h.cn/'
      domain2 = 'https://cloud.mk9h.cn:8443/'
    }
    Api.genericInterface(param).then(res => {
      // res.data = [{openid: 'o2E7gvoSFvQRG7I8_gZxf4y3ONkQ', send_id: '2223333', first: '您的缴费信息如下', keyword1: '010000000001', keyword2: '2022年07月03日', keyword3: '供暖缴费', keyword4: '20元', keyword5: '成功', remark: '感谢您的使用!'}]
      // res.send_data = [{openid: 'o2E7gvoSFvQRG7I8_gZxf4y3ONkQ', send_id: Utils.getuuid(), p1: '010000000001', p2: '明科', p3: 'dddd', p4: '顺风', p5: '成功'}]
      if (!res.status) {
        notification.warning({
          top: 92,
@@ -2133,7 +2155,12 @@
          duration: 5
        })
        return
      } else if (!res.send_data || res.send_data.length === 0) {
      }
      let sends = res.send_data || []
      sends = sends.filter(item => !!item.openid)
      if (sends.length === 0) {
        return
      }
@@ -2157,13 +2184,13 @@
      }
      
      verify.wxNoteKeys.forEach(item => {
        _param.data[item.key] = {value: '', color: item.color}
        _param.data[item.key] = {value: ''}
      })
      let params = res.send_data.map(item => {
      let params = sends.map(item => {
        let m = fromJS(_param).toJS()
        m.touser = item.openid || ''
        m.touser = item.openid
        if (item.bid && m.miniprogram && m.miniprogram.pagepath.indexOf('MenuId') > -1) {
          m.miniprogram.pagepath = m.miniprogram.pagepath + `&BID=${item.bid}`
        }
@@ -2181,21 +2208,25 @@
        return m
      })
      Api.wxAccessToken().then(res => {
      Api.wxAccessToken(domain1).then(res => {
        if (!res.oa_access_token) return
  
        params.forEach(n => {
          if (!n.touser) return
          Api.wxNginxRequest(`cgi-bin/message/template/send?access_token=${res.oa_access_token}`, 'post', n).then(re => {
          Api.wxNginxRequest(`${domain2}cgi-bin/message/template/send?access_token=${res.oa_access_token}`, 'post', n).then(re => {
            if (verify.wxNoteCallback === 'true') {
              let msg = re.errmsg || ''
              if (msg.length > 50) {
                msg = msg.substr(0, 50)
              }
              let _p = {
                func: 's_get_sms_weixin_local_suc_err',
                upid: id,
                send_id: n.client_msg_id || '',
                status_result: re.errcode === 0 ? 'S' : 'E',
                errcode: re.errcode,
                msg_result: re.errmsg
                msg_result: msg
              }
              _p.LText = Utils.formatOptions(Utils.getuuid())
@@ -2605,7 +2636,8 @@
        fieldlen: item.fieldlength || 50,
        writein: item.writein !== 'false',
        type: item.type,
        value: item.initval
        value: item.initval,
        isconst: item.constant === 'true'
      }
      let key = item.field.toLowerCase()
src/tabviews/zshare/actionList/printbutton/index.jsx
@@ -2127,7 +2127,8 @@
        fieldlen: item.fieldlength || 50,
        writein: item.writein !== 'false',
        type: item.type,
        value: item.initval
        value: item.initval,
        isconst: item.constant === 'true'
      }
      let key = item.field.toLowerCase()
src/tabviews/zshare/mutilform/index.jsx
@@ -1073,7 +1073,8 @@
            readin: item.readin,
            writein: item.writein,
            fieldlen: item.fieldlength,
            key: item.field
            key: item.field,
            isconst: item.constant === 'true'
          }
    
          _item.value = record[item.field] !== undefined ? record[item.field] : ''
src/tabviews/zshare/settingcomponent/index.jsx
@@ -143,9 +143,13 @@
            })
          })
        } else if (item.type === 'table') {
          item.cols && item.cols.forEach(col => {
            if (col.type !== 'action') return
            col.elements && col.elements.forEach(cell => {
          let loopCol = (cols) => {
            cols.forEach(col => {
              if (col.type === 'colspan') {
                loopCol(col.subcols)
              } else if (col.type === 'custom') {
                col.elements.forEach(cell => {
                  if (cell.eleType !== 'button') return
              cell.$expanded = false
              if (cell.OpenType === 'funcbutton' && cell.funcType === 'print') {
@@ -165,8 +169,11 @@
              _comp.action.push({...cell, $line: true, ...(userConfig[cell.uuid] || {})})
            })
              }
          })
        } 
          loopCol(item.cols)
        }
        
        if (_comp.action.length > 0) {
          _components.push(_comp)
src/templates/comtableconfig/updatetable/index.jsx
@@ -279,8 +279,9 @@
                }
              })
              tab.components[0].cols.forEach(col => {
                if (col.type !== 'action') return
                if (col.type !== 'custom') return
                col.elements.forEach(btn => {
                  if (btn.eleType !== 'button') return
                  if (btn.OpenType === 'popview') {
                    if (menus[btn.uuid]) {
                      let mainTb = {name: '主表', uuid: Utils.getuuid(), useMSearch: 'false'}
@@ -330,8 +331,9 @@
              }
            })
            item.cols.forEach(col => {
              if (col.type !== 'action') return
              if (col.type !== 'custom') return
              col.elements.forEach(btn => {
                if (btn.eleType !== 'button') return
                if (btn.OpenType === 'popview') {
                  if (menus[btn.uuid]) {
                    let mainTb = {name: '主表', uuid: Utils.getuuid(), useMSearch: 'false'}
@@ -450,8 +452,9 @@
                }
              })
              tab.components[0].cols.forEach(col => {
                if (col.type !== 'action') return
                if (col.type !== 'custom') return
                col.elements.forEach(btn => {
                  if (btn.eleType !== 'button') return
                  if (btn.OpenType === 'popview' && btn.config && btn.config.components[0]) {
                    this.setTbForm(btn.config.components[0], menus, errors, tab.components[0].name + '-' + btn.label)
                  } else if (btn.OpenType === 'pop' || (btn.OpenType === 'funcbutton' && btn.funcType === 'print' && btn.execMode === 'pop')) {
@@ -487,8 +490,9 @@
              }
            })
            item.cols.forEach(col => {
              if (col.type !== 'action') return
              if (col.type !== 'custom') return
              col.elements.forEach(btn => {
                if (btn.eleType !== 'button') return
                if (btn.OpenType === 'popview' && btn.config && btn.config.components[0]) {
                  this.setTbForm(btn.config.components[0], menus, errors, item.name + '-' + btn.label)
                } else if (btn.OpenType === 'pop' || (btn.OpenType === 'funcbutton' && btn.funcType === 'print' && btn.execMode === 'pop')) {
@@ -531,8 +535,9 @@
      }
    })
    item.cols.forEach(col => {
      if (col.type !== 'action') return
      if (col.type !== 'custom') return
      col.elements.forEach(btn => {
        if (btn.eleType !== 'button') return
        if (btn.OpenType === 'pop' || (btn.OpenType === 'funcbutton' && btn.funcType === 'print' && btn.execMode === 'pop')) {
          if (menus[btn.uuid]) {
            btn.modal = {
@@ -580,8 +585,9 @@
            }
          })
          tab.components[0].cols.forEach(col => {
            if (col.type !== 'action') return
            if (col.type !== 'custom') return
            col.elements.forEach(btn => {
              if (btn.eleType !== 'button') return
              if (btn.OpenType === 'popview' && btn.config) {
                btn.config.$tables = getTables(btn.config.components[0])
              }
@@ -597,8 +603,9 @@
          }
        })
        item.cols.forEach(col => {
          if (col.type !== 'action') return
          if (col.type !== 'custom') return
          col.elements.forEach(btn => {
            if (btn.eleType !== 'button') return
            if (btn.OpenType === 'popview' && btn.config) {
              btn.config.$tables = getTables(btn.config.components[0])
            }
@@ -1169,7 +1176,7 @@
        marks: [],
        isSub: false,
        uuid: Utils.getuuid(),
        type: 'action',
        type: 'custom',
        Width: 120,
        elements: colbtns,
        style: {paddingTop: '12px', paddingLeft: '8px', paddingBottom: '12px', paddingRight: '8px'}
@@ -1237,10 +1244,10 @@
    })
    _card.cols.forEach(col => {
      if (col.type !== 'action') return
      if (col.type !== 'custom') return
      col.elements.forEach(cell => {
        if (cell.hidden === 'true') return
        if (cell.hidden === 'true' || cell.eleType !== 'button') return
        if (cell.OpenType === 'pop' || (cell.OpenType === 'funcbutton' && cell.execMode === 'pop')) {
          if (!cell.modal || cell.modal.fields.length === 0) {
            _card.errors.push({ level: 0, detail: `按钮“${cell.label}”中表单尚未添加`})
src/templates/sharecomponent/actioncomponent/verifyexcelin/customscript/index.jsx
@@ -61,19 +61,39 @@
  }
  edit = (record) => {
    const { type } = this.props
    this.setState({
      editItem: record
    })
    if (type === 'fullscreen') {
      this.props.form.setFieldsValue({
        sql: record.sql
      })
    } else {
    this.props.form.setFieldsValue({
      sql: record.sql,
      position: record.position || 'back'
    })
  }
  }
  handleConfirm = () => {
    const { type } = this.props
    const { editItem } = this.state
    // 表单提交时检查输入值是否正确
    this.props.form.validateFieldsAndScroll((err, values) => {
      if (type === 'fullscreen' && err) {
        notification.warning({
          top: 92,
          message: '请输入sql!',
          duration: 5
        })
        return
      }
      if (!err) {
        if (/^[\s\n]+$/.test(values.sql)) {
          notification.warning({
@@ -84,7 +104,11 @@
          return
        }
        
        values.uuid = this.state.editItem ? this.state.editItem.uuid : ''
        values.uuid = editItem ? editItem.uuid : ''
        if (type === 'fullscreen' && editItem) {
          values.status = editItem.status || 'true'
        }
        let _quot = values.sql.match(/'{1}/g)
        let _lparen = values.sql.match(/\({1}/g)
@@ -258,6 +282,9 @@
    }
    let _sql = this.props.form.getFieldValue('sql')
    if (/^\s+$/.test(_sql)) {
      _sql = ''
    }
    if (_sql) {
      _sql = _sql + ` 
@@ -276,8 +303,8 @@
  }
  render() {
    const { systemScripts, btn } = this.props
    const { usefulfields } = this.state
    const { systemScripts, btn, type } = this.props
    const { usefulfields, editItem } = this.state
    const { getFieldDecorator } = this.props.form
    const formItemLayout = {
      labelCol: {
@@ -293,24 +320,24 @@
    return (
      <Form {...formItemLayout} className="verify-form" id="verify-excelin-custom-scripts">
        <Row gutter={24}>
          {btn.sheet ? <Col span={8}>
          {!type && btn.sheet ? <Col span={8}>
            <Form.Item label={'表名'} style={{whiteSpace: 'nowrap', margin: 0}}>
              {btn.sheet}
            </Form.Item>
          </Col> : null}
          <Col span={10}>
          {!type ? <Col span={10}>
            <Form.Item label={'报错字段'} style={{margin: 0, whiteSpace: 'nowrap'}}>
              ErrorCode(增加后缀NT表示数据不回滚,如ENT、NNT、FNT、NMNT), retmsg
            </Form.Item>
          </Col>
          <Col span={24} className="sqlfield">
          </Col> : null}
          {!type ? <Col span={24} className="sqlfield">
            <Form.Item label={'可用字段'}>
              <Tooltip mouseLeaveDelay={0.3} mouseEnterDelay={0.3} placement="top" title={'公共值,请按照@xxx@格式使用。'}><span style={{color: '#1890ff'}}>BID, ID, LoginUID, SessionUid, UserID, Appkey, time_id, typename</span></Tooltip>,&nbsp;
              <Tooltip mouseLeaveDelay={0.3} mouseEnterDelay={0.3} placement="top" title={'系统变量,系统会定义变量并赋值。'}><span style={{color: '#fa8c16'}}>UserName, FullName, RoleID, mk_departmentcode, mk_organization, mk_user_type, mk_nation, mk_province, mk_city, mk_district, mk_address</span></Tooltip>,&nbsp;
              {usefulfields}
            </Form.Item>
          </Col>
          <Col span={8} style={{whiteSpace: 'nowrap'}}>
          </Col> : null}
          {!type ? <Col span={8} style={{whiteSpace: 'nowrap'}}>
            <Form.Item style={{marginBottom: 0}} label={
              <Tooltip placement="bottomLeft" title={'自定义脚本与默认sql位置关系。'}>
                <QuestionCircleOutlined className="mk-form-tip" />
@@ -327,8 +354,8 @@
                </Radio.Group>
              )}
            </Form.Item>
          </Col>
          <Col span={10}>
          </Col> : null}
          {!type ? <Col span={10}>
            <Form.Item style={{marginBottom: 0}} label={'快捷添加'}>
              <Select
                showSearch
@@ -349,10 +376,10 @@
                )}
              </Select>
            </Form.Item>
          </Col>
          </Col> : null}
          <Col span={6} className="add">
            <Button onClick={this.handleConfirm} loading={this.state.loading} className="mk-green" style={{marginBottom: 15, marginLeft: 40}}>
              保存
            {type === 'fullscreen' && !editItem ? '添加' : '保存'}
            </Button>
            <Button onClick={this.handleCancel} style={{marginBottom: 15, marginLeft: 10}}>
              取消
src/templates/sharecomponent/actioncomponent/verifyexcelin/index.jsx
@@ -19,6 +19,7 @@
const { confirm } = Modal
const { Paragraph } = Typography
const EditTable = asyncComponent(() => import('@/templates/zshare/editTable'))
const FullScripts = asyncComponent(() => import('@/templates/zshare/verifycard/fullScripts'))
class VerifyCard extends Component {
  static propTpyes = {
@@ -464,6 +465,7 @@
  changeColumns = (columns) => {
    const { verify } = this.state
    let reset = false
    columns = columns.map(col => {
      col.type = col.type || 'Nvarchar(50)'
      if (col.type === 'text' || col.type === 'image') {
@@ -476,8 +478,14 @@
        col.limit = col.type.match(/\d+/) ? col.type.match(/\d+/)[0] : '20000'
      } else if (/^Decimal/ig.test(col.type)) {
        col.limit = col.type.match(/\d+/ig)[1]
        if (col.required === 'false') {
          reset = true
        }
        col.required = 'true'
      } else if (/^int/ig.test(col.type)) {
        if (col.required === 'false') {
          reset = true
        }
        col.required = 'true'
      } else {
        col.limit = ''
@@ -488,6 +496,10 @@
      return col
    })
    if (reset) {
      message.warn('数值类型均为必填。')
    }
    this.setState({verify: {...verify, columns}}, () => {
      this.resetUniqueColumns()
@@ -844,6 +856,23 @@
              {verify.scripts.length ? <span className="count-tip">{verify.scripts.length}</span> : null}
            </span>
          } key="scripts" id="mk-exin-script">
            <FullScripts
              verify={verify}
              getScriptsFullForm={() => this.scriptsFullForm}
              getScriptsForm={() => this.scriptsForm}
              handleStatus={this.handleStatus}
              handleDelete={this.handleDelete}
            >
              <CustomScript
                type="fullscreen"
                btn={this.props.card}
                usefulfields={verify.columns}
                scripts={verify.scripts}
                systemScripts={this.state.systemScripts}
                scriptsChange={this.scriptsChange}
                wrappedComponentRef={(inst) => this.scriptsFullForm = inst}
              />
            </FullScripts>
            <CustomScript
              btn={this.props.card}
              usefulfields={verify.columns}
src/templates/sharecomponent/actioncomponent/verifyexcelin/index.scss
@@ -77,4 +77,12 @@
      z-index: 1;
    }
  }
  .full-scripts {
    position: absolute;
    right: 24px;
    top: 0px;
    font-size: 16px;
    color: #1890ff;
    z-index: 1;
  }
}
src/templates/sharecomponent/actioncomponent/verifyexcelout/customscript/index.jsx
@@ -115,7 +115,7 @@
    this.props.form.setFieldsValue({
      sql: record.sql,
      position: record.position || 'back'
      // position: record.position || 'back'
    })
  }
@@ -232,6 +232,9 @@
    }
    let _sql = this.props.form.getFieldValue('sql')
    if (/^\s+$/.test(_sql)) {
      _sql = ''
    }
    if (_sql) {
      _sql = _sql + ` 
src/templates/sharecomponent/actioncomponent/verifyexcelout/index.jsx
@@ -160,20 +160,20 @@
          )
        }
      },
      {
        title: '执行位置',
        dataIndex: 'position',
        width: '10%',
        render: (text, record) => {
          if (record.position === 'init') {
            return <span style={{color: 'orange'}}>初始化</span>
          } else if (record.position === 'front') {
            return <span style={{color: '#26C281'}}>sql前</span>
          } else {
            return <span style={{color: '#1890ff'}}>sql后</span>
          }
        }
      },
      // {
      //   title: '执行位置',
      //   dataIndex: 'position',
      //   width: '10%',
      //   render: (text, record) => {
      //     if (record.position === 'init') {
      //       return <span style={{color: 'orange'}}>初始化</span>
      //     } else if (record.position === 'front') {
      //       return <span style={{color: '#26C281'}}>sql前</span>
      //     } else {
      //       return <span style={{color: '#1890ff'}}>sql后</span>
      //     }
      //   }
      // },
      {
        title: '状态',
        dataIndex: 'status',
src/templates/zshare/codemirror/index.scss
@@ -117,6 +117,16 @@
    bottom: 20px;
  }
}
.model-custom-scripts-modal .code-mirror-wrap:not(.mk-fullscreen), .model-custom-view-scripts-modal .code-mirror-wrap:not(.mk-fullscreen) {
  .anticon-swap {
    position: absolute;
    z-index: 11;
    left: auto;
    right: 10px;
    top: auto;
    bottom: 20px;
  }
}
.mk-mirror-font {
  z-index: 1200!important;
}
src/templates/zshare/formconfig.jsx
@@ -3729,6 +3729,20 @@
    },
    {
      type: 'radio',
      key: 'constant',
      label: 'Unicode常量',
      tooltip: '使用时将在提交内容前加上 N,代表存入数据库时以 Unicode 格式存储。',
      initVal: card.constant || 'false',
      options: [{
        value: 'true',
        text: '使用'
      }, {
        value: 'false',
        text: '不使用'
      }]
    },
    {
      type: 'radio',
      key: 'sendType',
      label: '发送方式',
      initVal: card.sendType || 'local',
src/templates/zshare/modalform/index.jsx
@@ -19,7 +19,7 @@
const MkEditIcon = asyncComponent(() => import('@/components/mkIcon'))
const modalTypeOptions = {
  text: ['initval', 'readonly', 'required', 'hidden', 'readin', 'fieldlength', 'regular', 'interception', 'span', 'labelwidth', 'encryption', 'tooltip', 'extra', 'enter', 'cursor', 'scan', 'splitline', 'placeholder', 'place', 'marginTop', 'marginBottom', 'lenControl', 'inputType'],
  text: ['initval', 'readonly', 'required', 'hidden', 'readin', 'fieldlength', 'regular', 'interception', 'span', 'labelwidth', 'encryption', 'tooltip', 'extra', 'enter', 'cursor', 'scan', 'splitline', 'placeholder', 'place', 'marginTop', 'marginBottom', 'lenControl', 'inputType', 'constant'],
  number: ['initval', 'readonly', 'hidden', 'decimal', 'min', 'max', 'readin', 'span', 'labelwidth', 'tooltip', 'extra', 'enter', 'cursor', 'splitline', 'place', 'marginTop', 'marginBottom'],
  select: ['initval', 'readonly', 'required', 'hidden', 'readin', 'resourceType', 'declare', 'setAll', 'linkSubField', 'span', 'labelwidth', 'tooltip', 'extra', 'place', 'emptyText', 'enter', 'splitline', 'dropdown', 'marginTop', 'marginBottom', 'pickerMode'],
  checkbox: ['initval', 'readonly', 'required', 'hidden', 'readin', 'resourceType', 'fieldlength', 'span', 'labelwidth', 'tooltip', 'extra', 'place', 'splitline', 'arrange', 'marginTop', 'marginBottom'],
src/templates/zshare/verifycard/baseform/index.jsx
@@ -5,10 +5,9 @@
import { QuestionCircleOutlined } from '@ant-design/icons'
import Api from '@/api'
import asyncComponent from '@/utils/asyncComponent'
import './index.scss'
const ColorSketch = asyncComponent(() => import('@/mob/colorsketch'))
const sysTempsIds = ['8IFltwzyKcu15iA8fqSyb6m-pMa88a3ZTu0No3vDHgo', 'LOB-bbt9jVncGh7IOAUdESh1Sgzcbt62UwOqSqcK9ok']
class BillCodeForm extends Component {
  static propTpyes = {
@@ -26,7 +25,6 @@
  }
  componentDidMount() {
    const { verify } = this.props
    let wxTemps = sessionStorage.getItem('wxTemplates')
    if (window.GLOB.WXAppID && window.GLOB.nginx && !wxTemps) {
@@ -38,21 +36,22 @@
          Api.wxNginxRequest(`cgi-bin/template/get_all_private_template?access_token=${wxtoken}`, 'get').then(res => {
            let temps = []
            if (res.template_list) {
              temps = res.template_list.filter(item => item.primary_industry)
              let selectTemp = temps.filter(item => item.template_id === verify.wxTemplateId)[0]
              if (selectTemp) {
                selectTemp.content = selectTemp.content.replace(/\r\n|\n/g, '<br/>')
                selectTemp.example = selectTemp.example.replace(/\r\n|\n/g, '<br/>')
              temps = res.template_list.filter(item => {
                if (!item.primary_industry || sysTempsIds.includes(item.template_id)) return false
                if (item.content) {
                  item.content = item.content.replace('{{first.DATA}}\n', '').replace('\n{{remark.DATA}}', '')
              }
              this.setState({wxTemps: temps, selectTemp})
                return true
              })
            }
            sessionStorage.setItem('wxTemplates', JSON.stringify(temps))
            localStorage.setItem('wxTemplates', JSON.stringify(temps))
            localStorage.removeItem('wxTemplates')
            this.resetTemps(temps)
          })
        } else {
          sessionStorage.setItem('wxTemplates', JSON.stringify([]))
@@ -75,15 +74,50 @@
    } else if (wxTemps) {
      wxTemps = JSON.parse(wxTemps)
      let selectTemp = wxTemps.filter(item => item.template_id === verify.wxTemplateId)[0]
      this.resetTemps(wxTemps)
    }
  }
  resetTemps = (wxTemps) => {
    const { verify } = this.props
    let sysTemps = [
      {
        template_id: '8IFltwzyKcu15iA8fqSyb6m-pMa88a3ZTu0No3vDHgo',
        title: '订单受理通知(明科云)',
        primary_industry: 'IT科技',
        deputy_industry: 'IT软件与服务',
        content: '订单号:{{keyword1.DATA}}\n订单类型:{{keyword2.DATA}}\n订单状态:{{keyword3.DATA}}\n通知时间:{{keyword4.DATA}}',
        example: '订单号:20190101001\r\n订单类型:衣柜\r\n订单状态:设计完成\r\n通知时间:2019年1月1日12:30'
      },
      {
        template_id: 'LOB-bbt9jVncGh7IOAUdESh1Sgzcbt62UwOqSqcK9ok',
        title: '订单进度提醒(明科云)',
        primary_industry: 'IT科技',
        deputy_industry: 'IT软件与服务',
        content: '订单类型:{{keyword1.DATA}}\n订单号:{{keyword2.DATA}}\n订单状态:{{keyword3.DATA}}',
        example: '订单类型:退租申请\r\n订单号:TZ16101909\r\n订单状态:待取货'
      },
      {
        template_id: 'mk_category_temp',
        title: '类目模板',
        primary_industry: '',
        deputy_industry: '',
        content: '',
        example: ''
      }
    ]
    let _wxTemps = [...wxTemps, ...sysTemps]
    let selectTemp = _wxTemps.filter(item => item.template_id === verify.wxTemplateId)[0]
      if (selectTemp) {
        selectTemp.content = selectTemp.content.replace(/\r\n|\n/g, '<br/>')
        selectTemp.example = selectTemp.example.replace(/\r\n|\n/g, '<br/>')
      }
  
      this.setState({wxTemps, selectTemp})
    }
    this.setState({wxTemps: _wxTemps, selectTemp})
  }
  handleConfirm = () => {
@@ -97,10 +131,11 @@
    } else if (verify.wxNote === 'true') {
      if (!verify.wxTemplateId) {
        error = '开启公众号消息推送时,需要选择消息模板!'
      } else if (verify.wxTemplateId === 'mk_category_temp' && !verify.wxCustomTempId) {
        error = '开启公众号消息推送时,需要填写消息模板ID!'
      } else if (verify.wxNoteLink === 'url' && !verify.wxNoteLinkUrl) {
        error = '请填写网址!'
      }
    }
    return error
@@ -125,6 +160,8 @@
      _verify.wxNoteLinkMenuId = ''
      _verify.wxNoteCallback = 'false'
      _verify.wxNoteKeys = null
      delete _verify.wxCustomTempId
      if (this.state.selectTemp) {
        this.setState({selectTemp: null})
@@ -155,7 +192,7 @@
    const { verify } = this.props
    let _verify = {...verify, wxTemplateId: val}
    let selectTemp = {content: option.props.content.replace(/\r\n|\n/g, '<br/>'), example: option.props.example.replace(/\r\n|\n/g, '<br/>')}
    let selectTemp = {template_id: val, content: option.props.content.replace(/\r\n|\n/g, '<br/>'), example: option.props.example.replace(/\r\n|\n/g, '<br/>')}
    let keys = []
    if (option.props.content) {
@@ -163,26 +200,27 @@
      keys = keys.map(key => key.replace(/{{|\.DATA}}/g, ''))
    }
    delete _verify.wxCustomTempId
    if (selectTemp.template_id === 'mk_category_temp') {
      _verify.wxNoteKeys = []
      for (let i = 1; i <= 10; i++) {
        _verify.wxNoteKeys.push({
          key: '',
          value: 'p' + i
        })
      }
    } else {
    let index = 1
    _verify.wxNoteKeys = keys.map(key => {
      let item = {
        key: key,
        color: '#000000',
        readonly: false
      }
      if (key === 'first') {
        item.value = 'first'
        item.readonly = true
      } else if (key === 'remark') {
        item.value = 'remark'
        item.readonly = true
      } else {
        let item = { key: key }
        item.value = 'p' + index
        index++
      }
      return item
    })
    }
    this.setState({selectTemp})
@@ -203,16 +241,24 @@
    this.props.onChange(_verify)
  }
  onWxNoteColorChange = (key, val) => {
  onWxNoteValueChange = (value, val) => {
    let _verify = fromJS(this.props.verify).toJS()
    _verify.wxNoteKeys = _verify.wxNoteKeys.map(m => {
      if (m.key === key) {
        m.color = val
      if (m.value === value) {
        m.key = val.replace(/\s+/ig, '')
      }
      return m
    })
    this.props.onChange(_verify)
  }
  onWxNoteTempIdChange = (value) => {
    let _verify = fromJS(this.props.verify).toJS()
    _verify.wxCustomTempId = value.replace(/\s+/ig, '')
    this.props.onChange(_verify)
  }
@@ -413,9 +459,9 @@
              <Input placeholder="" autoComplete="off" value={verify.wxNoteLinkMenuId || ''} onChange={(e) => {this.onOptionChange(e.target.value, 'wxNoteLinkMenuId')}}/>
            </Form.Item>
          </Col> : null}
          {verify.wxNote === 'true' && verify.wxNoteKeys ? verify.wxNoteKeys.map(item => <Col span={8} key={item.key}>
            <Form.Item className="mk-note-keyword" label={item.key} required>
              <Select value={item.value} disabled={item.readonly} onSelect={(val) => this.onWxNoteKeyChange(item.key, val)}>
          {verify.wxNote === 'true' && verify.wxNoteKeys && (!selectTemp || selectTemp.template_id !== 'mk_category_temp') ? verify.wxNoteKeys.map((item, index) => <Col span={8} key={'mk' + index}>
            <Form.Item label={item.key} required>
              <Select value={item.value} onSelect={(val) => this.onWxNoteKeyChange(item.key, val)}>
                <Select.Option value="p1">p1</Select.Option>
                <Select.Option value="p2">p2</Select.Option>
                <Select.Option value="p3">p3</Select.Option>
@@ -427,10 +473,19 @@
                <Select.Option value="p9">p9</Select.Option>
                <Select.Option value="p10">p10</Select.Option>
              </Select>
              <ColorSketch value={item.color || '#ffffff'} onChange={(val, hex) => {this.onWxNoteColorChange(item.key, hex)}} />
            </Form.Item>
          </Col>) : null}
          {selectTemp && verify.wxNoteKeys ? <Col span={24} className="wx-note">
          {verify.wxNote === 'true' && verify.wxNoteKeys && (selectTemp && selectTemp.template_id === 'mk_category_temp') ? <Col span={8}>
            <Form.Item label="模板ID" required>
              <Input placeholder="" defaultValue={verify.wxCustomTempId} autoComplete="off" onChange={(e) => {this.onWxNoteTempIdChange(e.target.value)}}/>
            </Form.Item>
          </Col> : null}
          {verify.wxNote === 'true' && verify.wxNoteKeys && (selectTemp && selectTemp.template_id === 'mk_category_temp') ? verify.wxNoteKeys.map((item, index) => <Col span={8} key={'mk' + index}>
            <Form.Item label={item.value}>
              <Input placeholder="" defaultValue={item.key} autoComplete="off" onChange={(e) => {this.onWxNoteValueChange(item.value, e.target.value)}}/>
            </Form.Item>
          </Col>) : null}
          {selectTemp && selectTemp.template_id !== 'mk_category_temp' && verify.wxNoteKeys ? <Col span={24} className="wx-note">
            <div className="note-wrap">
              <div className="note">
                <p>内容示例</p>
@@ -449,12 +504,25 @@
                <div>
                  <p>openid:&nbsp;&nbsp;"接收者openid",</p>
                  <p>send_id:&nbsp;&nbsp;"防重入id",</p>
                  {verify.wxNoteKeys.map(item => <p>{item.value}:&nbsp;&nbsp;"=&gt; {item.key}",</p>)}
                  {verify.wxNoteKeys.map((item, i) => <p key={'index' + i}>{item.value}:&nbsp;&nbsp;"=&gt; {item.key}",</p>)}
                  <p>bid:&nbsp;&nbsp;"跳转小程序时,可作为BID。"</p>
                </div>
              </div>
            </div>
          </Col> : null}
          {selectTemp && selectTemp.template_id === 'mk_category_temp' && verify.wxNoteKeys ? <Col span={24} className="wx-note">
            <div className="note-wrap">
              <div className="note">
                <p>消息体</p>
                <div>
                  <p>openid:&nbsp;&nbsp;"接收者openid",</p>
                  <p>send_id:&nbsp;&nbsp;"防重入id",</p>
                  <p>bid:&nbsp;&nbsp;"跳转小程序时,可作为BID。"</p>
                  <p style={{color: '#1890ff'}}>请在通用字段中(p1~p10)填入模板中对应的字段名,如 time1.DATA 则填写 time1。</p>
                </div>
              </div>
            </div>
          </Col> : null}
        </Row>
      </Form>
    )
src/templates/zshare/verifycard/baseform/index.scss
@@ -1,29 +1,3 @@
.mk-note-keyword {
  .ant-select {
    width: 50%;
    .ant-select-selection {
      border-radius: 4px 0px 0px 4px;
    }
  }
  .color-sketch-block {
    width: 50%;
    display: inline-block;
    vertical-align: top;
    position: relative;
    top: 4px;
    .color-sketch-block-box {
      width: calc(100% - 75px);
      height: 32px;
      border-radius: 0px 4px 4px 0px;
      .color-sketch-block-inner {
        border-radius: 0px 4px 4px 0px;
      }
    }
    .color-sketch-value {
      width: 75px;
    }
  }
}
.wx-note {
  display: flex;
  .note-wrap {
src/templates/zshare/verifycard/billcodeform/index.jsx
@@ -4,7 +4,7 @@
import { Form, Row, Col, Select, Button, InputNumber, Input, Tooltip } from 'antd'
import { QuestionCircleOutlined } from '@ant-design/icons'
import './index.scss'
// import './index.scss'
class BillCodeForm extends Component {
  static propTpyes = {
src/templates/zshare/verifycard/contrastform/index.jsx
@@ -1,7 +1,7 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import { Form, Row, Col, Select, Button, Input } from 'antd'
import './index.scss'
// import './index.scss'
class UniqueForm extends Component {
  static propTpyes = {
src/templates/zshare/verifycard/customform/index.jsx
@@ -6,7 +6,7 @@
import Utils from '@/utils/utils.js'
import Api from '@/api'
import CodeMirror from '@/templates/zshare/codemirror'
import './index.scss'
// import './index.scss'
class CustomForm extends Component {
  static propTpyes = {
src/templates/zshare/verifycard/fullScripts/index.jsx
New file
@@ -0,0 +1,130 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import { Modal, notification, Typography, Popconfirm } from 'antd'
import { CheckCircleOutlined, StopOutlined, SwapOutlined, DeleteOutlined, BorderOutlined } from '@ant-design/icons'
import MinView from '@/assets/img/minview.png'
import './index.scss'
const { Paragraph } = Typography
class fullScripts extends Component {
  static propTpyes = {
    verify: PropTypes.object,
    getScriptsForm: PropTypes.func
  }
  state = {
    visible: false,
    scriptId: '',
    columns: []
  }
  trigger = () => {
    const { getScriptsForm } = this.props
    let scriptsForm = getScriptsForm()
    if (scriptsForm) {
      let sql = scriptsForm.props.form.getFieldValue('sql') || ''
      if (scriptsForm.state.editItem || (sql && !/^\s+$/.test(sql))) {
        notification.warning({
          top: 92,
          message: '请保存自定义脚本!',
          duration: 5
        })
        return
      }
    }
    this.setState({visible: true, scriptId: ''})
  }
  render() {
    const { verify, children } = this.props
    const { visible, scriptId } = this.state
    return (
      <>
        <BorderOutlined className="full-scripts" onClick={this.trigger}/>
        <Modal
          wrapClassName="model-custom-scripts-modal"
          title="自定义脚本"
          visible={visible}
          width={'95vw'}
          maskClosable={false}
          destroyOnClose
        >
          <img className="unfull-scripts" src={MinView} onClick={() => this.setState({visible: false, scriptId: ''})} alt=""/>
          <div className="script-table-wrap">
            {verify.scripts.map(item => {
              let title = item.sql.match(/^\s*\/\*.+\*\//)
              title = title && title[0] ? title[0] : ''
              let _text = title ? item.sql.replace(title, '') : item.sql
              let position = null
              if (item.position === 'init') {
                position = <span style={{color: 'orange'}}>初始化</span>
              } else if (item.position === 'front') {
                position = <span style={{color: '#26C281'}}>sql前</span>
              } else {
                position = <span style={{color: '#1890ff'}}>sql后</span>
              }
              if (item.status === 'false') {
                return (
                  <div className="script-item" key={item.uuid}>
                    <div style={{cursor: 'not-allowed'}}>
                      {title ? <div style={{color: '#a50', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis'}}>{title}</div> : null}
                      <Paragraph copyable={{ text: item.sql }} ellipsis={{ rows: 4 }}>{_text}</Paragraph>
                      <div>{position}
                        <span style={{color: '#ff4d4f', marginLeft: '20px'}}>
                          禁用
                          <StopOutlined style={{marginLeft: '5px'}} />
                        </span>
                      </div>
                    </div>
                    <div style={{height: '24px'}}></div>
                  </div>
                )
              } else {
                return (
                  <div className={'script-item ' + (scriptId === item.uuid ? 'active' : '') } key={item.uuid}>
                    <div style={{cursor: 'pointer'}} onClick={() => {
                      let scriptsFullForm = this.props.getScriptsFullForm()
                      scriptsFullForm && scriptsFullForm.edit(item)
                      this.setState({scriptId: item.uuid})
                    }}>
                      {title ? <div style={{color: '#a50', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis'}}>{title}</div> : null}
                      <Paragraph copyable={{ text: item.sql }} ellipsis={{ rows: 4 }}>{_text}</Paragraph>
                      <div>{position}
                        <span style={{color: '#26C281', marginLeft: '20px'}}>
                          启用
                          <CheckCircleOutlined style={{marginLeft: '5px'}}/>
                        </span>
                      </div>
                    </div>
                    <div style={{textAlign: 'right'}}>
                      <span className="operation-btn" onClick={() => this.props.handleStatus(item, 'scripts')} style={{color: '#8E44AD'}}><SwapOutlined /></span>
                      <Popconfirm
                        overlayClassName="popover-confirm"
                        title="确定删除吗?"
                        onConfirm={() => this.props.handleDelete(item, 'scripts')
                      }>
                        <span className="operation-btn" style={{color: '#ff4d4f'}}><DeleteOutlined /></span>
                      </Popconfirm>
                    </div>
                  </div>
                )
              }
            })}
          </div>
          {visible ? children : null}
        </Modal>
      </>
    )
  }
}
export default fullScripts
src/templates/zshare/verifycard/fullScripts/index.scss
New file
@@ -0,0 +1,130 @@
.model-custom-scripts-modal {
  .ant-modal {
    top: 30px;
    .ant-modal-header {
      padding: 10px 24px;
    }
    .ant-modal-footer {
      display: none;
    }
    .ant-modal-close {
      display: none;
    }
    .ant-modal-body {
      padding: 0;
      height: calc(100vh - 100px);
      overflow: hidden;
      display: flex;
      .script-table-wrap {
        width: 240px;
        overflow-y: auto;
        overflow-x: hidden;
        height: calc(100vh - 100px);
        .operation-btn {
          display: inline-block;
          font-size: 16px;
          padding: 0 5px;
          cursor: pointer;
          margin-left: 5px;
        }
        .script-item {
          border-bottom: 1px solid #eeeeee;
          padding: 15px 10px 5px;
        }
        .script-item.active {
          background-color: #bae7ff;
        }
        .ant-typography {
          margin-bottom: 5px;
        }
      }
      .script-table-wrap::-webkit-scrollbar {
        width: 7px;
      }
      .script-table-wrap::-webkit-scrollbar-thumb {
        border-radius: 5px;
        box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.13);
        background: rgba(0, 0, 0, 0.13);
      }
      .script-table-wrap::-webkit-scrollbar-track {
        box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.05);
        border-radius: 3px;
        border: 1px solid rgba(0, 0, 0, 0.07);
        background: rgba(0, 0, 0, 0);
      }
      .unfull-scripts {
        position: absolute;
        right: 20px;
        z-index: 2;
        top: 10px;
        color: #1890ff;
        width: 26px;
        cursor: pointer;
        padding: 5px;
      }
      .verify-form {
        flex: 1;
        >.ant-row {
          margin: 0!important;
          position: unset;
        }
        .sql {
          padding: 0!important;
          .ant-form-item-label {
            display: none;
          }
          .ant-form-item-control-wrapper {
            width: 100%;
          }
          .CodeMirror {
            height: calc(100vh - 100px);
            border-radius: 0;
          }
          .code-mirror-area {
            border-radius: 0;
            width: calc(95vw - 240px);
          }
        }
        .sqlfield {
          .ant-form-item {
            margin-bottom: 5px;
          }
          .ant-form-item-control {
            line-height: 24px;
          }
          .ant-form-item-label {
            line-height: 25px;
          }
          .ant-form-item-children {
            line-height: 22px;
          }
          .ant-col-sm-8 {
            width: 10.5%;
          }
          .ant-col-sm-16 {
            width: 89.5%;
          }
        }
        .add {
          position: absolute;
          top: 10px;
          z-index: 1;
          .ant-btn {
            height: 28px;
          }
          .mk-green {
            margin-left: 0!important;
            margin-right: 10px;
          }
        }
      }
    }
  }
}
src/templates/zshare/verifycard/index.jsx
@@ -2,7 +2,7 @@
import PropTypes from 'prop-types'
import { is, fromJS } from 'immutable'
import { Form, Tabs, Row, Col, Button, Popconfirm, notification, Modal, message, InputNumber, Typography } from 'antd'
import { CheckCircleOutlined, StopOutlined, EditOutlined, SwapOutlined, DeleteOutlined, ExclamationOutlined, BorderOutlined } from '@ant-design/icons'
import { CheckCircleOutlined, StopOutlined, EditOutlined, SwapOutlined, DeleteOutlined, ExclamationOutlined } from '@ant-design/icons'
import Toast from 'antd-mobile/es/components/toast'
import Dialog from 'antd-mobile/es/components/dialog'
import moment from 'moment'
@@ -21,13 +21,13 @@
import asyncComponent from '@/utils/asyncComponent'
import { updateForm } from '@/utils/utils-update.js'
import MKEmitter from '@/utils/events.js'
import MinView from '@/assets/img/minview.png'
import './index.scss'
const { TabPane } = Tabs
const { confirm } = Modal
const { Paragraph } = Typography
const EditTable = asyncComponent(() => import('@/templates/zshare/editTable'))
const FullScripts = asyncComponent(() => import('./fullScripts'))
class VerifyCard extends Component {
  static propTpyes = {
@@ -44,8 +44,6 @@
    appType: sessionStorage.getItem('appType'),
    notes: [],              // 短信模板
    setting: null,
    visible: false,
    scriptId: '',
    verify: {},
    fields: [],
    usefulfields: '',
@@ -1540,7 +1538,7 @@
  render() {
    const { card } = this.props
    const { activeKey, verifyInter, setting, verify, fields, visible, uniqueFields, uniqueColumns, unionFields, onceUniqueColumns, columnsFields, contrastColumns, customColumns, orderColumns, scriptsColumns, cbScriptsColumns, orderModular, orderModularDetail, voucher, voucherDetail, notes, appType } = this.state
    const { activeKey, verifyInter, setting, verify, fields, uniqueFields, uniqueColumns, unionFields, onceUniqueColumns, columnsFields, contrastColumns, customColumns, orderColumns, scriptsColumns, cbScriptsColumns, orderModular, orderModularDetail, voucher, voucherDetail, notes, appType } = this.state
    const formItemLayout = {
      labelCol: {
        xs: { span: 24 },
@@ -1640,17 +1638,25 @@
              {verify.scripts.length ? <span className="count-tip">{verify.scripts.length}</span> : null}
            </span>
          } key="scripts" id="mk-normal-script">
            <BorderOutlined className="full-scripts" onClick={() => {
              if (this.scriptsForm && (this.scriptsForm.state.editItem || (this.scriptsForm.props.form.getFieldValue('sql') && !/^\s+$/.test(this.scriptsForm.props.form.getFieldValue('sql'))))) {
                notification.warning({
                  top: 92,
                  message: '请保存自定义脚本!',
                  duration: 5
                })
                return
              }
              this.setState({visible: true, scriptId: ''})
            }}/>
            <FullScripts
              verify={verify}
              getScriptsFullForm={() => this.scriptsFullForm}
              getScriptsForm={() => this.scriptsForm}
              handleStatus={this.handleStatus}
              handleDelete={this.handleDelete}
            >
              <CustomScript
                type="fullscreen"
                btn={this.props.card}
                initsql={this.state.initsql}
                customScripts={verify.scripts}
                defaultsql={this.state.defaultsql}
                usefulfields={this.state.usefulfields}
                systemScripts={this.state.systemScripts}
                scriptsChange={this.scriptsChange}
                wrappedComponentRef={(inst) => this.scriptsFullForm = inst}
              />
            </FullScripts>
            <CustomScript
              btn={this.props.card}
              initsql={this.state.initsql}
@@ -1768,89 +1774,6 @@
            </Form>
          </TabPane>
        </Tabs>
        <Modal
          wrapClassName="model-custom-scripts-modal"
          title="自定义脚本"
          visible={visible}
          width={'95vw'}
          maskClosable={false}
          destroyOnClose
        >
          <img className="unfull-scripts" src={MinView} onClick={() => this.setState({visible: false, scriptId: ''})} alt=""/>
          <div className="script-table-wrap">
            {verify.scripts.map(item => {
              let title = item.sql.match(/^\s*\/\*.+\*\//)
              title = title && title[0] ? title[0] : ''
              let _text = title ? item.sql.replace(title, '') : item.sql
              let position = null
              if (item.position === 'init') {
                position = <span style={{color: 'orange'}}>初始化</span>
              } else if (item.position === 'front') {
                position = <span style={{color: '#26C281'}}>sql前</span>
              } else {
                position = <span style={{color: '#1890ff'}}>sql后</span>
              }
              if (item.status === 'false') {
                return (
                  <div className="script-item" key={item.uuid}>
                    <div style={{cursor: 'not-allowed'}}>
                      {title ? <div style={{color: '#a50', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis'}}>{title}</div> : null}
                      <Paragraph copyable={{ text: item.sql }} ellipsis={{ rows: 4 }}>{_text}</Paragraph>
                      <div>{position}
                        <span style={{color: '#ff4d4f', marginLeft: '20px'}}>
                          禁用
                          <StopOutlined style={{marginLeft: '5px'}} />
                        </span>
                      </div>
                    </div>
                    <div style={{height: '24px'}}></div>
                  </div>
                )
              } else {
                return (
                  <div className={'script-item ' + (this.state.scriptId === item.uuid ? 'active' : '') } key={item.uuid}>
                    <div style={{cursor: 'pointer'}} onClick={() => {
                      this.scriptsFullForm.edit(item)
                      this.setState({scriptId: item.uuid})
                    }}>
                      {title ? <div style={{color: '#a50', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis'}}>{title}</div> : null}
                      <Paragraph copyable={{ text: item.sql }} ellipsis={{ rows: 4 }}>{_text}</Paragraph>
                      <div>{position}
                        <span style={{color: '#26C281', marginLeft: '20px'}}>
                          启用
                          <CheckCircleOutlined style={{marginLeft: '5px'}}/>
                        </span>
                      </div>
                    </div>
                    <div style={{textAlign: 'right'}}>
                      <span className="operation-btn" onClick={() => this.handleStatus(item, 'scripts')} style={{color: '#8E44AD'}}><SwapOutlined /></span>
                      <Popconfirm
                        overlayClassName="popover-confirm"
                        title="确定删除吗?"
                        onConfirm={() => this.handleDelete(item, 'scripts')
                      }>
                        <span className="operation-btn" style={{color: '#ff4d4f'}}><DeleteOutlined /></span>
                      </Popconfirm>
                    </div>
                  </div>
                )
              }
            })}
          </div>
          <CustomScript
            type="fullscreen"
            btn={this.props.card}
            initsql={this.state.initsql}
            customScripts={verify.scripts}
            defaultsql={this.state.defaultsql}
            usefulfields={this.state.usefulfields}
            systemScripts={this.state.systemScripts}
            scriptsChange={this.scriptsChange}
            wrappedComponentRef={(inst) => this.scriptsFullForm = inst}
          />
        </Modal>
      </div>
    )
  }
src/templates/zshare/verifycard/index.scss
@@ -89,136 +89,6 @@
    z-index: 1;
  }
}
.model-custom-scripts-modal {
  .ant-modal {
    top: 30px;
    .ant-modal-header {
      padding: 10px 24px;
    }
    .ant-modal-footer {
      display: none;
    }
    .ant-modal-close {
      display: none;
    }
    .ant-modal-body {
      padding: 0;
      height: calc(100vh - 100px);
      overflow: hidden;
      display: flex;
      .script-table-wrap {
        width: 240px;
        overflow-y: auto;
        overflow-x: hidden;
        height: calc(100vh - 100px);
        .operation-btn {
          display: inline-block;
          font-size: 16px;
          padding: 0 5px;
          cursor: pointer;
          margin-left: 5px;
        }
        .script-item {
          border-bottom: 1px solid #eeeeee;
          padding: 15px 10px 5px;
        }
        .script-item.active {
          background-color: #bae7ff;
        }
        .ant-typography {
          margin-bottom: 5px;
        }
      }
      .script-table-wrap::-webkit-scrollbar {
        width: 7px;
      }
      .script-table-wrap::-webkit-scrollbar-thumb {
        border-radius: 5px;
        box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.13);
        background: rgba(0, 0, 0, 0.13);
      }
      .script-table-wrap::-webkit-scrollbar-track {
        box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.05);
        border-radius: 3px;
        border: 1px solid rgba(0, 0, 0, 0.07);
        background: rgba(0, 0, 0, 0);
      }
      .unfull-scripts {
        position: absolute;
        right: 20px;
        z-index: 2;
        top: 10px;
        color: #1890ff;
        width: 26px;
        cursor: pointer;
        padding: 5px;
      }
      .verify-form {
        flex: 1;
        >.ant-row {
          margin: 0!important;
          position: unset;
        }
        .sql {
          padding: 0!important;
          .ant-form-item-label {
            display: none;
          }
          .ant-form-item-control-wrapper {
            width: 100%;
          }
          .CodeMirror {
            height: calc(100vh - 100px);
            border-radius: 0;
          }
          .code-mirror-area {
            border-radius: 0;
            width: calc(95vw - 240px);
          }
        }
        .sqlfield {
          .ant-form-item {
            margin-bottom: 5px;
          }
          .ant-form-item-control {
            line-height: 24px;
          }
          .ant-form-item-label {
            line-height: 25px;
          }
          .ant-form-item-children {
            line-height: 22px;
          }
          .ant-col-sm-8 {
            width: 10.5%;
          }
          .ant-col-sm-16 {
            width: 89.5%;
          }
        }
        .add {
          position: absolute;
          top: 10px;
          z-index: 1;
          .ant-btn {
            height: 28px;
          }
          .mk-green {
            margin-left: 0!important;
            margin-right: 10px;
          }
        }
      }
    }
  }
}
.adm-mask {
  z-index: 2000!important;
}
src/templates/zshare/verifycard/uniqueform/index.jsx
@@ -1,7 +1,7 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import { Form, Row, Col, Select, Button } from 'antd'
import './index.scss'
// import './index.scss'
class UniqueForm extends Component {
  static propTpyes = {
src/templates/zshare/verifycard/voucherform/index.jsx
@@ -2,7 +2,7 @@
import PropTypes from 'prop-types'
import { is, fromJS } from 'immutable'
import { Form, Row, Col, Select, Switch, notification } from 'antd'
import './index.scss'
// import './index.scss'
class UniqueForm extends Component {
  static propTpyes = {
src/utils/utils-custom.js
@@ -517,73 +517,40 @@
          })
        }
      } else if (item.type === 'table' && item.cols) {
        let loopCol = (col) => {
          col.subcols = col.subcols.map(c => {
            c.uuid = md5(commonId + c.uuid)
        let loopCol = (cols) => {
          return cols.map(col => {
            if (col.type === 'action') {
              col.type = 'custom'
            }
  
            if (c.type === 'colspan' && c.subcols) {
              c = loopCol(c)
            } else if (c.type === 'custom' && c.elements) {
              c.elements = c.elements.map(cell => {
                cell.uuid = this.getuuid()
            col.uuid = md5(commonId + col.uuid)
                return cell
              })
            } else if (c.type === 'action' && c.elements) {
              c.elements = c.elements.map(cell => {
            if (col.type === 'colspan' && col.subcols) {
              col.subcols = loopCol(col.subcols)
            } else if (col.type === 'custom' && col.elements) {
              col.elements = col.elements.map(cell => {
                cell.uuid = md5(commonId + cell.uuid)
                if (cell.eleType === 'button') {
                if (clear && cell.pageTemplate === 'linkpage' && cell.linkmenu) {
                  cell.pageTemplate = ''
                  cell.linkmenu = ''
                }
                this.resetBtn(cell, commonId)
                }
                return cell
              })
            }
            return c
          })
          return col
        }
        item.cols = item.cols.map(col => {
          col.uuid = md5(commonId + col.uuid)
          if (col.type === 'colspan' && col.subcols) {
            col = loopCol(col)
          } else if (col.type === 'custom' && col.elements) {
            col.elements = col.elements.map(cell => {
              cell.uuid = this.getuuid()
              return cell
            })
          } else if (col.type === 'action' && col.elements) {
            col.elements = col.elements.map(cell => {
              cell.uuid = md5(commonId + cell.uuid)
              this.resetBtn(cell, commonId)
              return cell
            })
          }
          return col
        })
        if (item.subtype === 'editable') {
          item.cols = item.cols.map(col => {
            if (col.editable === 'true' && col.enter) {
            } else if (col.editable === 'true' && col.enter) {
              col.enter = md5(commonId + col.enter)
            } else if (col.type === 'colspan' && col.subcols) {
              col.subcols = col.subcols.map(c => {
                if (c.editable === 'true' && c.enter) {
                  c.enter = md5(commonId + c.enter)
                }
                return c
              })
            }
            return col
          })
        }
        item.cols = loopCol(item.cols)
      } else if (item.type === 'form') {
        item.subcards = item.subcards.map(cell => {
          cell.uuid = this.getuuid()
@@ -831,40 +798,23 @@
        })
      }
    } else if (item.type === 'table' && item.cols) {
      let loopCol = (col) => {
        col.subcols = col.subcols.map(c => {
          c.uuid = this.getuuid()
          if (c.type === 'colspan' && c.subcols) {
            c = loopCol(c)
          } else if (c.type === 'custom' && c.elements) {
            c.elements = c.elements.map(cell => {
              cell.uuid = this.getuuid()
              return cell
            })
          }
          return c
        })
        return col
      let loopCol = (cols) => {
        return cols.map(col => {
          if (col.type === 'action') {
            col.type = 'custom'
      }
      item.cols = item.cols.map(col => {
        col.uuid = md5(commonId + col.uuid)
        if (col.type === 'colspan' && col.subcols) {
          col = loopCol(col)
            col.subcols = loopCol(col.subcols)
        } else if (col.type === 'custom' && col.elements) {
          col.elements = col.elements.map(cell => {
            cell.uuid = this.getuuid()
            return cell
          })
        } else if (col.type === 'action' && col.elements) {
          if (sessionStorage.getItem('editMenuType') === 'popview') {
            col.elements = col.elements.filter(c => c.OpenType !== 'popview' && c.OpenType !== 'funcbutton')
              col.elements = col.elements.filter(c => c.eleType !== 'button' || (c.OpenType !== 'popview' && c.OpenType !== 'funcbutton'))
          }
          col.elements = col.elements.map(cell => {
            cell.uuid = md5(commonId + cell.uuid)
              if (cell.eleType === 'button') {
            if (cell.OpenType === 'pop' || (cell.OpenType === 'funcbutton' && cell.execMode === 'pop')) {
              if (cell.modal && cell.modal.fields.length > 0) {
                cell.modal.fields = cell.modal.fields.map(m => {
@@ -873,21 +823,18 @@
                })
              }
            }
              }
            return cell
          })
        }
        return col
      })
      if (item.subtype === 'editable') {
        item.cols = item.cols.map(col => {
          if (col.editable === 'true' && col.enter) {
          } else if (col.editable === 'true' && col.enter) { // 可编辑表
            col.enter = md5(commonId + col.enter)
          }
          return col
        })
      }
      item.cols = loopCol(item.cols)
    } else if (item.type === 'form') {
      item.subcards = item.subcards.map(cell => {
        cell.uuid = this.getuuid()
@@ -1094,9 +1041,14 @@
    })
  }
  config.cols && config.cols.forEach(col => {
    if (col.type === 'action') {
  if (config.cols) {
    let loopCol = (cols) => {
      cols.forEach(col => {
        if (col.type === 'colspan') {
          loopCol(col.subcols)
        } else if (col.type === 'custom') {
      col.elements.forEach(cell => {
            if (cell.eleType !== 'button') return
        if (['form', 'pop', 'prompt', 'exec', 'excelIn', 'excelOut'].includes(cell.OpenType)) {
          action.push(cell)
        } else if (cell.OpenType === 'funcbutton' && cell.funcType === 'print' && cell.verify) {
@@ -1111,6 +1063,9 @@
      })
    }
  })
    }
    loopCol(config.cols)
  }
  config.elements && config.elements.forEach(cell => {
    if (cell.eleType !== 'button') return
@@ -1394,8 +1349,9 @@
  if (card.$c_cl) {
    card.cols.forEach(col => {
      if (col.type === 'action') {
      if (col.type === 'custom') {
        col.elements.forEach(cell => {
          if (cell.eleType === 'button') {
          if (cell.hidden === 'true') return
          if (cell.OpenType === 'pop' || (cell.OpenType === 'funcbutton' && cell.execMode === 'pop')) {
            if (!cell.modal || cell.modal.fields.length === 0) {
@@ -1410,12 +1366,11 @@
          if (doubleClick === cell.uuid) {
            doubleClick = ''
          }
        })
      } else if (col.type === 'custom') {
        col.elements.forEach(cell => {
          } else {
          if (cell.datatype === 'dynamic' && cell.field && !columns.includes(cell.field)) {
            errors.push({ level: 1, detail: `显示列“${col.label}”中动态字段“${cell.field}”无效`})
          }
          }
        })
      } else if (col.field && !columns.includes(col.field)) {
        errors.push({ level: 1, detail: `显示列“${col.label}”中字段“${col.field}”无效`})
src/utils/utils.js
@@ -960,9 +960,7 @@
      let _position = (_topline + lindex + 1) + '行 ' + _colindex + '列 '
      if (/^Nvarchar/ig.test(col.type)) {
        if (typeof(val) === 'number') {
          val = val.toString()
        }
        val = val + ''
        if (/'/.test(val)) {
          val = val.replace(/'/ig, '"')
@@ -982,38 +980,15 @@
            }
          })
        }
      } else if (/^int/ig.test(col.type)) {
      } else if (/^Decimal/ig.test(col.type) || /^int/ig.test(col.type)) {
        if (!val && val !== 0) {
          errors.push(_position + '内容不可为空')
        } else {
          let _val = val + ''
          if (!/^(([^0][0-9]+|0)$)|^(([1-9]+)$)/.test(_val)) {               // 检验是否为整数
            errors.push(_position + '内容应为整数')
        } else if (isNaN(val)) {                                  // 检验是否为数值
          errors.push(_position + '内容应为数值')
          } else if ((col.min || col.min === 0) && val < col.min) {          // 最小值检验
            errors.push(_position + '小于最小值')
          } else if ((col.max || col.max === 0) && val > col.max) {          // 最大值检验
            errors.push(_position + '大于最大值')
          }
        }
      } else if (/^Decimal/ig.test(col.type)) {
        if (!val && val !== 0) {
          errors.push(_position + '内容不可为空')
        } else {
          let _val = val + ''
          let _vals = _val.split('.')
          if (!/^(([^0][0-9]+|0)\.([0-9]+)$)|^(([^0][0-9]+|0)$)|^(([1-9]+)\.([0-9]+)$)|^(([1-9]+)$)/.test(_val)) {                           // 检验是否为浮点数
            errors.push(_position + '内容应为浮点数')
          } else if (_vals[0].length > 18) {                          // 检验整数位
            errors.push(_position + '整数位超出范围')
          } else if (_vals[1] && _vals[1].length > col.limit) {       // 最小值检验
            errors.push(_position + '小数位超出范围')
          } else if ((col.min || col.min === 0) && val < col.min) {   // 最小值检验
            errors.push(_position + '小于最小值')
          } else if ((col.max || col.max === 0) && val > col.max) {   // 最大值检验
            errors.push(_position + '大于最大值')
          }
        }
      } else if (col.type === 'date') {
        if (typeof(val) === 'number') {
@@ -1488,9 +1463,13 @@
        if (/'/.test(val)) {
          val = val.replace(/'/ig, '"')
        }
        if (form.isconst) {
          _initFormfields.push(`@${_key}=N'${val}'`)
        } else {
        _initFormfields.push(`@${_key}='${val}'`)
      }
    }
    }
    
    if (!_vars.includes(_key)) {
      _vars.push(_key)
src/views/billprint/index.jsx
@@ -333,19 +333,27 @@
          if (component.type === 'table') {
            let getColumns = (cols) => {
              return cols.map(item => {
              return cols.filter(item => {
                if (item.type === 'colspan') {
                  item.subcols = getColumns(item.subcols)
                  if (item.subcols.length === 0) {
                    return false
                  }
                } else if (item.type === 'custom') {
                  item.elements = item.elements.map(cell => {
                  item.elements = item.elements.filter(cell => {
                    if (cell.eleType === 'button') return false
                    cell = this.resetElement(cell)
                    return cell
                  })
                  if (item.elements.length === 0) {
                    return false
                  }
                } else {
                  item.IsSort = 'false'
                }
          
                return item
                return true
              })
            }
            component.cols = getColumns(component.cols)
src/views/menudesign/index.jsx
@@ -370,6 +370,8 @@
      _btn.config.MenuID = _btn.uuid
      _btn.config.ParentId = card.uuid
      _btn.config.MenuName = _btn.label
      _btn.config.components = this.updateComponents(_btn.config.components || [])
    } else {
      _btn.config = {
        uuid: _btn.uuid,
@@ -485,6 +487,7 @@
          })
          this.updatePage(config)
        } else {
          config.components = this.updateComponents(config.components)
          this.setState({
            oriConfig: fromJS(config).toJS(),
            config: config
@@ -498,6 +501,27 @@
          duration: 5
        })
      }
    })
  }
  updateComponents = (components) => { // 兼容性升级 table
    return components.map(item => {
      if (item.type === 'tabs') {
        item.subtabs.forEach(tab => {
          tab.components = this.updateComponents(tab.components)
        })
      } else if (item.type === 'group') {
        item.components = this.updateComponents(item.components)
      } else if (item.type === 'table') {
        item.cols = item.cols.map(col => {
          if (col.type === 'action') {
            col.type = 'custom'
          }
          return col
        })
      }
      return item
    })
  }
@@ -519,6 +543,13 @@
      if (item.subtype === 'tablecard') { // 兼容
        item.type = 'card'
      } else if (item.type === 'table') {
        item.cols = item.cols.map(col => {
          if (col.type === 'action') {
            col.type = 'custom'
          }
          return col
        })
      }
      delete item.tabId
@@ -556,15 +587,23 @@
      })
    })
    config.cols && config.cols.forEach(col => {
      if (col.type === 'action') {
    if (config.cols) {
      let loopCol = (cols) => {
        cols.forEach(col => {
          if (col.type === 'colspan') {
            loopCol(col.subcols)
          } else if (col.type === 'custom') {
        col.elements.forEach(cell => {
              if (cell.eleType !== 'button') return
          if (cell.OpenType === 'popview' && popbtns[cell.uuid]) {
            cell.config = popbtns[cell.uuid]
          }
        })
      }
    })
      }
      loopCol(config.cols)
    }
    config.elements && config.elements.forEach(cell => {
      if (cell.eleType !== 'button') return
@@ -684,6 +723,11 @@
        if (item.$tables) {
          tbs.push(...item.$tables)
        }
        if (item.wrap && item.wrap.permission === 'false') {
          return
        }
        if (item.action && item.action.length > 0) {
          item.action.forEach(btn => {
            if (btn.hidden === 'true') return
@@ -720,15 +764,21 @@
            _sort++
          })
        } else if (item.type === 'table') {
          item.cols && item.cols.forEach(col => {
            if (col.type !== 'action') return
            col.elements.forEach(btn => {
              if (btn.hidden === 'true') return
              buttons.push(`select '${btn.uuid}' as menuid, '${item.name + '-' + btn.label}' as menuname, '${_sort * 10}' as Sort, '${config.uuid}' as parentid, 40 as Type`)
          let loopCol = (cols) => {
            cols.forEach(col => {
              if (col.type === 'colspan') {
                loopCol(col.subcols)
              } else if (col.type === 'custom') {
                col.elements.forEach(cell => {
                  if (cell.eleType !== 'button' || cell.hidden === 'true') return
                  buttons.push(`select '${cell.uuid}' as menuid, '${item.name + '-' + cell.label}' as menuname, '${_sort * 10}' as Sort, '${config.uuid}' as parentid, 40 as Type`)
              _sort++
            })
              }
          })
        }
          loopCol(item.cols)
        }
      })
    }
src/views/mobdesign/index.jsx
@@ -232,6 +232,8 @@
      _btn.config.MenuID = _btn.uuid
      _btn.config.ParentId = card.uuid
      _btn.config.MenuName = _btn.label
      _btn.config.components = this.updateComponents(_btn.config.components || [])
    } else {
      _btn.config = {
        uuid: _btn.uuid,
@@ -298,15 +300,23 @@
      })
    })
    config.cols && config.cols.forEach(col => {
      if (col.type === 'action') {
    if (config.cols) {
      let loopCol = (cols) => {
        cols.forEach(col => {
          if (col.type === 'colspan') {
            loopCol(col.subcols)
          } else if (col.type === 'custom') {
        col.elements.forEach(cell => {
              if (cell.eleType !== 'button') return
          if (cell.OpenType === 'popview' && popbtns[cell.uuid]) {
            cell.config = popbtns[cell.uuid]
          }
        })
      }
    })
      }
      loopCol(config.cols)
    }
    config.elements && config.elements.forEach(cell => {
      if (cell.eleType !== 'button') return
@@ -604,6 +614,8 @@
          this.setState({
            needUpdate: true
          })
        } else {
          config.components = this.updateComponents(config.components)
        }
        let navItem = null
@@ -823,6 +835,8 @@
          this.setState({
            needUpdate: true
          })
        } else {
          config.components = this.updateComponents(config.components)
        }
        config.enabled = false
@@ -921,6 +935,27 @@
    })
  }
  updateComponents = (components) => { // 兼容性升级 table
    return components.map(item => {
      if (item.type === 'tabs') {
        item.subtabs.forEach(tab => {
          tab.components = this.updateComponents(tab.components)
        })
      } else if (item.type === 'group') {
        item.components = this.updateComponents(item.components)
      } else if (item.type === 'table') {
        item.cols = item.cols.map(col => {
          if (col.type === 'action') {
            col.type = 'custom'
          }
          return col
        })
      }
      return item
    })
  }
  collectTB = (components) => {
    return components.map(item => {
      if (item.type === 'tabs') {
@@ -939,6 +974,13 @@
      if (item.subtype === 'tablecard') { // 兼容
        item.type = 'card'
      } else if (item.type === 'table') {
        item.cols = item.cols.map(col => {
          if (col.type === 'action') {
            col.type = 'custom'
          }
          return col
        })
      }
      delete item.tabId
@@ -1081,17 +1123,22 @@
              title: btn.label,
            })
          })
          item.cols && item.cols.forEach(col => {
            if (col.type !== 'action') return
            col.elements.forEach(btn => {
              if (btn.hidden === 'true') return
          let loopCol = (cols) => {
            cols.forEach(col => {
              if (col.type === 'colspan') {
                loopCol(col.subcols)
              } else if (col.type === 'custom') {
                col.elements.forEach(cell => {
                  if (cell.eleType !== 'button' || cell.hidden === 'true') return
              m.children.push({
                key: btn.uuid,
                title: btn.label,
                    key: cell.uuid,
                    title: cell.label,
              })
            })
              }
          })
          }
          loopCol(item.cols)
        }
        list.push(m)
@@ -1181,8 +1228,6 @@
              })
            }
            card.elements && card.elements.forEach(cell => {
              if (cell.eleType !== 'button') return
              if (cell.linkmenu && menuObj[cell.linkmenu]) {
                menus.push(menuObj[cell.linkmenu])
              } else if (cell.openmenu && menuObj[cell.openmenu]) {
@@ -1192,8 +1237,6 @@
            if (item.subtype === 'dualdatacard') {
              card.backElements && card.backElements.forEach(cell => {
                if (cell.eleType !== 'button') return
                if (cell.linkmenu && menuObj[cell.linkmenu]) {
                  menus.push(menuObj[cell.linkmenu])
                } else if (cell.openmenu && menuObj[cell.openmenu]) {
@@ -1204,8 +1247,6 @@
          })
        } else if (item.type === 'balcony') {
          item.elements && item.elements.forEach(cell => {
            if (cell.eleType !== 'button') return
            if (cell.linkmenu && menuObj[cell.linkmenu]) {
                menus.push(menuObj[cell.linkmenu])
              } else if (cell.openmenu && menuObj[cell.openmenu]) {
@@ -1226,16 +1267,22 @@
              menus.push(menuObj[btn.openmenu])
            }
          })
          item.cols && item.cols.forEach(col => {
            if (col.type !== 'action') return
            col.elements.forEach(btn => {
              if (btn.linkmenu && menuObj[btn.linkmenu]) {
                menus.push(menuObj[btn.linkmenu])
              } else if (btn.openmenu && menuObj[btn.openmenu]) {
                menus.push(menuObj[btn.openmenu])
          let loopCol = (cols) => {
            cols.forEach(col => {
              if (col.type === 'colspan') {
                loopCol(col.subcols)
              } else if (col.type === 'custom') {
                col.elements.forEach(cell => {
                  if (cell.linkmenu && menuObj[cell.linkmenu]) {
                    menus.push(menuObj[cell.linkmenu])
                  } else if (cell.openmenu && menuObj[cell.openmenu]) {
                    menus.push(menuObj[cell.openmenu])
              }
            })
              }
          })
          }
          loopCol(item.cols)
        }
      })
    }
@@ -1299,7 +1346,7 @@
            return cols.map(col => {
              if (col.type === 'colspan') {
                col.subcols = getCols(col.subcols || [])
              } else if (col.type === 'custom' || col.type === 'action') {
              } else if (col.type === 'custom') {
                col.elements = col.elements.map(cell => {
                  cell.miniStyle = this.transferStyle(cell.style)
                  return cell
src/views/pcdesign/index.jsx
@@ -365,6 +365,8 @@
      _btn.config.MenuID = _btn.uuid
      _btn.config.ParentId = card.uuid
      _btn.config.MenuName = _btn.label
      _btn.config.components = this.updateComponents(_btn.config.components || [])
    } else {
      _btn.config = {
        uuid: _btn.uuid,
@@ -420,15 +422,23 @@
      })
    })
    config.cols && config.cols.forEach(col => {
      if (col.type === 'action') {
    if (config.cols) {
      let loopCol = (cols) => {
        cols.forEach(col => {
          if (col.type === 'colspan') {
            loopCol(col.subcols)
          } else if (col.type === 'custom') {
        col.elements.forEach(cell => {
              if (cell.eleType !== 'button') return
          if (cell.OpenType === 'popview' && popbtns[cell.uuid]) {
            cell.config = popbtns[cell.uuid]
          }
        })
      }
    })
      }
      loopCol(config.cols)
    }
    config.elements && config.elements.forEach(cell => {
      if (cell.eleType !== 'button') return
@@ -556,6 +566,8 @@
          this.setState({
            needUpdate: true
          })
        } else {
          config.components = this.updateComponents(config.components)
        }
        let navItem = null
@@ -581,6 +593,27 @@
    this.getAppMenus()
  }
  updateComponents = (components) => { // 兼容性升级 table
    return components.map(item => {
      if (item.type === 'tabs') {
        item.subtabs.forEach(tab => {
          tab.components = this.updateComponents(tab.components)
        })
      } else if (item.type === 'group') {
        item.components = this.updateComponents(item.components)
      } else if (item.type === 'table') {
        item.cols = item.cols.map(col => {
          if (col.type === 'action') {
            col.type = 'custom'
          }
          return col
        })
      }
      return item
    })
  }
  collectTB = (components) => {
    return components.map(item => {
      if (item.type === 'tabs') {
@@ -599,6 +632,13 @@
      if (item.subtype === 'tablecard') { // 兼容
        item.type = 'card'
      } else if (item.type === 'table') {
        item.cols = item.cols.map(col => {
          if (col.type === 'action') {
            col.type = 'custom'
          }
          return col
        })
      }
      delete item.tabId
@@ -913,17 +953,22 @@
              title: btn.label,
            })
          })
          item.cols.forEach(col => {
            if (col.type !== 'action') return
            col.elements.forEach(btn => {
              if (btn.hidden === 'true') return
          let loopCol = (cols) => {
            cols.forEach(col => {
              if (col.type === 'colspan') {
                loopCol(col.subcols)
              } else if (col.type === 'custom') {
                col.elements.forEach(cell => {
                  if (cell.eleType !== 'button' || cell.hidden === 'true') return
              m.children.push({
                key: btn.uuid,
                title: btn.label,
                    key: cell.uuid,
                    title: cell.label,
              })
            })
              }
          })
          }
          loopCol(item.cols)
        }
        list.push(m)
@@ -996,8 +1041,6 @@
              })
            }
            card.elements && card.elements.forEach(cell => {
              if (cell.eleType !== 'button') return
              if (cell.linkmenu && menuObj[cell.linkmenu]) {
                menus.push(menuObj[cell.linkmenu])
              } else if (cell.openmenu && menuObj[cell.openmenu]) {
@@ -1006,8 +1049,6 @@
            })
            card.backElements && card.backElements.forEach(cell => {
              if (cell.eleType !== 'button') return
              if (cell.linkmenu && menuObj[cell.linkmenu]) {
                menus.push(menuObj[cell.linkmenu])
              } else if (cell.openmenu && menuObj[cell.openmenu]) {
@@ -1017,8 +1058,6 @@
          })
        } else if (item.type === 'balcony') {
          item.elements && item.elements.forEach(cell => {
            if (cell.eleType !== 'button') return
            if (cell.linkmenu && menuObj[cell.linkmenu]) {
                menus.push(menuObj[cell.linkmenu])
              } else if (cell.openmenu && menuObj[cell.openmenu]) {
@@ -1039,17 +1078,23 @@
              menus.push(menuObj[btn.openmenu])
            }
          })
          item.cols && item.cols.forEach(col => {
            if (col.type !== 'action') return
            col.elements.forEach(btn => {
              if (btn.linkmenu && menuObj[btn.linkmenu]) {
                menus.push(menuObj[btn.linkmenu])
              } else if (btn.openmenu && menuObj[btn.openmenu]) {
                menus.push(menuObj[btn.openmenu])
          let loopCol = (cols) => {
            cols.forEach(col => {
              if (col.type === 'colspan') {
                loopCol(col.subcols)
              } else if (col.type === 'custom') {
                col.elements.forEach(cell => {
                  if (cell.linkmenu && menuObj[cell.linkmenu]) {
                    menus.push(menuObj[cell.linkmenu])
                  } else if (cell.openmenu && menuObj[cell.openmenu]) {
                    menus.push(menuObj[cell.openmenu])
              }
            })
              }
          })
        }
          loopCol(item.cols)
        }
      })
    }
src/views/tabledesign/index.jsx
@@ -235,6 +235,26 @@
      _btn.config.MenuID = _btn.uuid
      _btn.config.ParentId = card.uuid
      _btn.config.MenuName = _btn.label
      _btn.config.components = _btn.config.components || []
      _btn.config.components.forEach(item => {
        if (item.type === 'tabs') {
          item.subtabs.forEach(tab => {
            tab.components[0].cols = tab.components[0].cols.map(col => {
              if (col.type === 'action') {
                col.type = 'custom'
              }
              return col
            })
          })
        } else if (item.cols) {
          item.cols = item.cols.map(col => {
            if (col.type === 'action') {
              col.type = 'custom'
            }
            return col
          })
        }
      })
    } else {
      _btn.config = {
        uuid: _btn.uuid,
@@ -263,6 +283,21 @@
  submitPopConfig = (btnconfig) => {
    let config = fromJS(this.state.config).toJS()
    let loopCol = (cols) => {
      cols.forEach(col => {
        if (col.type === 'colspan') {
          loopCol(col.subcols)
        } else if (col.type === 'custom') {
          col.elements.forEach(cell => {
            if (cell.eleType !== 'button') return
            if (cell.OpenType === 'popview' && cell.uuid === btnconfig.uuid) {
              cell.config = btnconfig
            }
          })
        }
      })
    }
    config.components.forEach(item => {
      if (item.type === 'tabs') {
        item.subtabs.forEach(tab => {
@@ -273,14 +308,8 @@
              btn.config = btnconfig
            }
          })
          tab.components[0].cols.forEach(col => {
            if (col.type !== 'action') return
            col.elements.forEach(btn => {
              if (btn.OpenType === 'popview' && btn.uuid === btnconfig.uuid) {
                btn.config = btnconfig
              }
            })
          })
          loopCol(tab.components[0].cols)
          tab.components[0].$tables = getTables(tab.components[0])
        })
@@ -290,14 +319,8 @@
            btn.config = btnconfig
          }
        })
        item.cols.forEach(col => {
          if (col.type !== 'action') return
          col.elements.forEach(btn => {
            if (btn.OpenType === 'popview' && btn.uuid === btnconfig.uuid) {
              btn.config = btnconfig
            }
          })
        })
        loopCol(item.cols)
        item.$tables = getTables(item)
      }
@@ -407,8 +430,20 @@
            if (item.type === 'tabs') {
              item.subtabs.forEach(tab => {
                tab.components[0].name = tab.label
                tab.components[0].cols = tab.components[0].cols.map(col => {
                  if (col.type === 'action') {
                    col.type = 'custom'
                  }
                  return col
                })
              })
            } else {
              item.cols = item.cols.map(col => {
                if (col.type === 'action') {
                  col.type = 'custom'
                }
                return col
              })
              item.name = '主表'
            }
          })
@@ -457,15 +492,22 @@
            buttons.push(`select '${btn.uuid}' as menuid, '${btn.label}' as menuname, '${_s * 10}' as Sort, '${tab.components[0].uuid}' as parentid, 60 as Type`)
            _s++
          })
          tab.components[0].cols.forEach(col => {
            if (col.type !== 'action') return
            col.elements.forEach(btn => {
              if (btn.hidden === 'true') return
              buttons.push(`select '${btn.uuid}' as menuid, '${btn.label}' as menuname, '${_s * 10}' as Sort, '${tab.components[0].uuid}' as parentid, 60 as Type`)
          let loopCol = (cols) => {
            cols.forEach(col => {
              if (col.type === 'colspan') {
                loopCol(col.subcols)
              } else if (col.type === 'custom') {
                col.elements.forEach(cell => {
                  if (cell.eleType !== 'button' || cell.hidden === 'true') return
                  buttons.push(`select '${cell.uuid}' as menuid, '${cell.label}' as menuname, '${_s * 10}' as Sort, '${tab.components[0].uuid}' as parentid, 60 as Type`)
              _s++
            })
              }
          })
          }
          loopCol(tab.components[0].cols)
        })
      } else {
        if (item.$tables) {
@@ -477,16 +519,23 @@
          buttons.push(`select '${btn.uuid}' as menuid, '${btn.label}' as menuname, '${_sort * 10}' as Sort, '${config.uuid}' as parentid, 40 as Type`)
          _sort++
        })
        item.cols.forEach(col => {
          if (col.type !== 'action') return
          col.elements.forEach(btn => {
            if (btn.hidden === 'true') return
            buttons.push(`select '${btn.uuid}' as menuid,  '${btn.label}' as menuname, '${_sort * 10}' as Sort, '${config.uuid}' as parentid, 40 as Type`)
        let loopCol = (cols) => {
          cols.forEach(col => {
            if (col.type === 'colspan') {
              loopCol(col.subcols)
            } else if (col.type === 'custom') {
              col.elements.forEach(cell => {
                if (cell.eleType !== 'button' || cell.hidden === 'true') return
                buttons.push(`select '${cell.uuid}' as menuid,  '${cell.label}' as menuname, '${_sort * 10}' as Sort, '${config.uuid}' as parentid, 40 as Type`)
            _sort++
          })
            }
        })
      }
        loopCol(item.cols)
      }
    })
    return buttons
src/views/tabledesign/source.jsx
@@ -231,12 +231,6 @@
      label: '序号',
      subType: 'index',
      $init: true
    },
    {
      type: 'col',
      label: '操作',
      subType: 'action',
      $init: true
    }
  ],
  tabItems: [