king
2021-01-22 c7df5603e14b98d6f80da425fab31d30574ca417
2021-01-22
14个文件已修改
2个文件已添加
1437 ■■■■ 已修改文件
src/api/index.js 25 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/header/index.jsx 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/setupProxy.js 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/formtab/index.jsx 19 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/actionList/normalbutton/index.jsx 658 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/mutilform/index.jsx 62 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/calendarconfig/tabcomponent/tabform/index.jsx 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/actioncomponent/actionform/index.jsx 98 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/actioncomponent/actionform/index.scss 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/actioncomponent/index.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/tabscomponent/tabform/index.jsx 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/zshare/formconfig.jsx 121 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/zshare/verifycard/callbackcustomscript/index.jsx 273 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/zshare/verifycard/callbackcustomscript/index.scss 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/zshare/verifycard/index.jsx 132 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/utils.js 12 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/index.js
@@ -46,7 +46,6 @@
  } else if (config.url.includes('Upload') || config.url.includes('doupload') || config.url.includes('dopreload')) {
    config.headers = { 'Content-Type': 'multipart/form-data' }
  } else if (config.method === 'post') {
    // config.headers.token = sessionStorage.getItem('TOKEN') || ''
    config.data = JSON.stringify(config.data)
  }
@@ -90,7 +89,7 @@
      duration: 15
    })
  }
  return Promise.reject(error)
  return Promise.reject(error.response)
})
class Api {
@@ -121,12 +120,24 @@
   * @param {Object} param 查询及提交参数
   */
  directRequest (url, method, param) {
    let params = { method: 'post' }
    let _url = url
    return axios({
      url: url,
      method: method,
      params: param
    })
    if (method === 'get' && param) {
      let keys = Object.keys(param).map(key => `${key}=${param[key]}`)
      keys = keys.join('&')
      if (keys) {
        _url = _url + '?' + keys
      }
    } else if (method === 'post' && param) {
      params.data = param
    }
    _url = window.btoa(_url)
    params.url = '/trans/redirect?rd=' + _url + '&method=' + method
    return axios(params)
  }
  /**
src/components/header/index.jsx
@@ -674,7 +674,9 @@
      })
    }, 1000)
    // Api.directRequest('https://www.sogou.com/suggnew/ajajjson', 'get', {type: 'web', key: '#content#'})
    // Api.directRequest('https://www.sogou.com/suggnew/ajajjson', 'get', {type: 'web', key: '#content#'}).then(res => {
    // }, (e) => {
    // })
  }
  shouldComponentUpdate (nextProps, nextState) {
src/setupProxy.js
@@ -39,4 +39,13 @@
    '^/wxpay': '/'
    }
  }))
  app.use(proxy('/trans', {
    target: `${host}/${service}trans`,
    secure: false,
    changeOrigin: true,
    pathRewrite: {
    '^/trans': '/'
    }
  }))
}
src/tabviews/formtab/index.jsx
@@ -673,16 +673,15 @@
                        {_tab.label}
                      </span>
                    } key={`${index}`}>
                      {_tab.type === 'SubTable' ?
                        <SubTable
                          Tab={_tab}
                          MenuID={_tab.linkTab}
                          SupMenuID={this.props.MenuID}
                          ContainerId={this.state.ContainerId}
                          BID={this.state.BIDs[_tab.supMenu] || ''}
                          BData={this.state.BIDs[_tab.supMenu + 'data'] || ''}
                          handleTableId={this.handleTableId}
                        /> : null}
                      <SubTable
                        Tab={_tab}
                        MenuID={_tab.linkTab}
                        SupMenuID={this.props.MenuID}
                        ContainerId={this.state.ContainerId}
                        BID={this.state.BIDs[_tab.supMenu] || ''}
                        BData={this.state.BIDs[_tab.supMenu + 'data'] || ''}
                        handleTableId={this.handleTableId}
                      />
                    </TabPane>
                  )
                })}
src/tabviews/zshare/actionList/normalbutton/index.jsx
@@ -147,13 +147,25 @@
        this.actionSettingError()
        return
      }
    } else if (btn.intertype === 'custom') {
      if (!btn.innerFunc && (!btn.sql || !btn.sqlType)) {
        this.actionSettingError()
        return
      } else if (!btn.innerFunc && data.length === 0 && btn.verify && btn.verify.voucher && btn.verify.voucher.enabled) {
        notification.warning({
          top: 92,
          message: '使用创建凭证函数,需要选择行!',
          duration: 5
        })
        return
      }
    } else if (btn.intertype === 'outer') {
      // 接口地址不存在时报错
      if (!btn.interface && btn.sysInterface !== 'true') {
        this.actionSettingError()
        return
      }
    } else if (!['inner', 'outer', 'system'].includes(btn.intertype)) {
    } else if (!['inner', 'outer', 'system', 'custom'].includes(btn.intertype)) {
      // 接口类型错误
      this.actionSettingError()
      return
@@ -196,92 +208,172 @@
    }
  }
  /**
   * @description 按钮提交执行
   */
  execSubmit = (data, _resolve, formdata) => {
  getSystemParam = (data, formdata, retmsg) => {
    const { setting, columns, btn } = this.props
    if (btn.intertype === 'inner' || btn.intertype === 'system') {
      // 执行方式为多行拼接,且打开方式为表单时,会转为循环发送请求
      // 打开方式为模态框,使用内部函数添加(有批量添加场景,已去除)
      if (
        btn.Ot === 'notRequired' ||
        btn.Ot === 'requiredSgl' ||
        btn.Ot === 'requiredOnce'
      ) {
        let param = { // 系统存储过程
    let _params = []
    if ( btn.Ot === 'notRequired' || btn.Ot === 'requiredSgl' || btn.Ot === 'requiredOnce' ) {
      let param = { // 系统存储过程
        func: 'sPC_TableData_InUpDe'
      }
      let check_param = null
      if (this.props.BID) {
        param.BID = this.props.BID
      }
      let primaryId = ''
      if (btn.Ot === 'requiredSgl' || btn.Ot === 'requiredOnce') {
        let ids = data.map(d => { return d[setting.primaryKey] || ''})
        ids = ids.filter(Boolean)
        primaryId = ids.join(',')
      }
      if (btn.OpenType === 'prompt' || btn.OpenType === 'exec') { // 是否弹框或直接执行
        param.ID = primaryId
        param.LText = Utils.getSysDefaultSql(btn, setting, '', param, data[0], columns, this.props.Tab, retmsg) // 数据源
        if (sessionStorage.getItem('dataM') === 'true') { // 数据权限
          param.LText = param.LText.replace(/\$@/ig, '/*')
          param.LText = param.LText.replace(/@\$/ig, '*/')
        } else {
          param.LText = param.LText.replace(/@\$|\$@/ig, '')
        }
        param.exec_type = 'y' // 后台解码
        param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
        param.secretkey = Utils.encrypt('', param.timestamp)
        if (/\$check@|@check\$/ig.test(param.LText)) {
          check_param = fromJS(param).toJS()
          check_param.LText = check_param.LText.replace(/\$check@/ig, '/*')
          check_param.LText = check_param.LText.replace(/@check\$/ig, '*/')
          check_param.LText = Utils.formatOptions(check_param.LText)
          param.LText = param.LText.replace(/\$check@|@check\$/ig, '')
        }
        param.LText = Utils.formatOptions(param.LText)
      } else if (btn.OpenType === 'pop') { // 表单
        if (btn.sqlType === 'insert') { // 系统函数添加时,生成uuid
          primaryId = ''
          if (formdata && setting.primaryKey) { // 表单中存在主键字段,主键值以表单中的值为准
            let _form = formdata.filter(_form => _form.key === setting.primaryKey)[0]
            if (_form) {
              primaryId = _form.value
            }
          }
          param.ID = primaryId || Utils.getguid()
          param.LText = Utils.getSysDefaultSql(btn, setting, formdata, param, data[0], columns, this.props.Tab, retmsg) // 数据源
          if (sessionStorage.getItem('dataM') === 'true') { // 数据权限
            param.LText = param.LText.replace(/\$@/ig, '/*')
            param.LText = param.LText.replace(/@\$/ig, '*/')
          } else {
            param.LText = param.LText.replace(/@\$|\$@/ig, '')
          }
          param.exec_type = 'y' // 后台解码
          param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
          param.secretkey = Utils.encrypt('', param.timestamp)
          if (/\$check@|@check\$/ig.test(param.LText)) {
            check_param = fromJS(param).toJS()
            check_param.LText = check_param.LText.replace(/\$check@/ig, '/*')
            check_param.LText = check_param.LText.replace(/@check\$/ig, '*/')
            check_param.LText = Utils.formatOptions(check_param.LText)
            param.LText = param.LText.replace(/\$check@|@check\$/ig, '')
          }
          param.LText = Utils.formatOptions(param.LText)
        } else {
          param.ID = primaryId
          param.LText = Utils.getSysDefaultSql(btn, setting, formdata, param, data[0], columns, this.props.Tab, retmsg) // 数据源
          if (sessionStorage.getItem('dataM') === 'true') { // 数据权限
            param.LText = param.LText.replace(/\$@/ig, '/*')
            param.LText = param.LText.replace(/@\$/ig, '*/')
          } else {
            param.LText = param.LText.replace(/@\$|\$@/ig, '')
          }
          param.exec_type = 'y' // 后台解码
          param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
          param.secretkey = Utils.encrypt('', param.timestamp)
          if (/\$check@|@check\$/ig.test(param.LText)) {
            check_param = fromJS(param).toJS()
            check_param.LText = check_param.LText.replace(/\$check@/ig, '/*')
            check_param.LText = check_param.LText.replace(/@check\$/ig, '*/')
            check_param.LText = Utils.formatOptions(check_param.LText)
            param.LText = param.LText.replace(/\$check@|@check\$/ig, '')
          }
          param.LText = Utils.formatOptions(param.LText)
        }
      }
      if (this.props.menuType === 'HS') { // 函数 sPC_TableData_InUpDe 云端验证
        param.open_key = Utils.encryptOpenKey(param.secretkey, param.timestamp)
        if (check_param) {
          check_param.open_key = Utils.encryptOpenKey(check_param.secretkey, check_param.timestamp)
        }
      }
      param.menuname = btn.logLabel
      if (check_param) {
        check_param.menuname = btn.logLabel
        this.setState({checkParam: check_param})
      }
      _params.push(param)
    } else if (btn.Ot === 'required') {
      _params = data.map((cell, index) => {
        let param = {
          func: 'sPC_TableData_InUpDe'
        }
        let check_param = null
        if (this.props.BID) {
          param.BID = this.props.BID
        }
        let primaryId = ''
        if (btn.Ot === 'requiredSgl' || btn.Ot === 'requiredOnce') {
          let ids = data.map(d => { return d[setting.primaryKey] || ''})
          ids = ids.filter(Boolean)
          primaryId = ids.join(',')
        }
        let primaryId = setting.primaryKey ? cell[setting.primaryKey] || '' : ''
        if (btn.OpenType === 'prompt' || btn.OpenType === 'exec') { // 是否弹框或直接执行
          if (btn.innerFunc) { // 使用自定义函数
            param.func = btn.innerFunc
            if (setting.primaryKey) { // 主键存在时,设置主键参数
              param[setting.primaryKey] = primaryId
            }
          } else if (btn.sql) {
            param.ID = primaryId
            param.LText = Utils.getSysDefaultSql(btn, setting, '', param, data[0], columns, this.props.Tab) // 数据源
            if (sessionStorage.getItem('dataM') === 'true') { // 数据权限
              param.LText = param.LText.replace(/\$@/ig, '/*')
              param.LText = param.LText.replace(/@\$/ig, '*/')
            } else {
              param.LText = param.LText.replace(/@\$|\$@/ig, '')
            }
            param.exec_type = 'y' // 后台解码
            param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
            param.secretkey = Utils.encrypt('', param.timestamp)
            if (/\$check@|@check\$/ig.test(param.LText)) {
              check_param = fromJS(param).toJS()
              check_param.LText = check_param.LText.replace(/\$check@/ig, '/*')
              check_param.LText = check_param.LText.replace(/@check\$/ig, '*/')
              check_param.LText = Utils.formatOptions(check_param.LText)
              param.LText = param.LText.replace(/\$check@|@check\$/ig, '')
            }
            param.LText = Utils.formatOptions(param.LText)
          param.ID = primaryId
          param.LText = Utils.getSysDefaultSql(btn, setting, '', param, cell, columns, this.props.Tab, retmsg) // 数据源
          if (sessionStorage.getItem('dataM') === 'true') { // 数据权限
            param.LText = param.LText.replace(/\$@/ig, '/*')
            param.LText = param.LText.replace(/@\$/ig, '*/')
          } else {
            param.LText = param.LText.replace(/@\$|\$@/ig, '')
          }
          param.LText = param.LText.replace(/\$check@|@check\$/ig, '')
          param.exec_type = 'y' // 后台解码
          param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
          param.secretkey = Utils.encrypt('', param.timestamp)
          param.LText = Utils.formatOptions(param.LText)
        } else if (btn.OpenType === 'pop') { // 表单
          if (btn.innerFunc) {
            param.func = btn.innerFunc
            if (setting.primaryKey) { // 主键存在时,设置主键参数
              param[setting.primaryKey] = primaryId
            }
            formdata.forEach(_data => {
              param[_data.key] = _data.value
            })
          } else if (btn.sql && btn.sqlType === 'insert') { // 系统函数添加时,生成uuid
            primaryId = ''
            if (formdata && setting.primaryKey) { // 表单中存在主键字段,主键值以表单中的值为准
              let _form = formdata.filter(_form => _form.key === setting.primaryKey)[0]
              if (_form) {
                primaryId = _form.value
          if (index !== 0) {
            formdata = formdata.map(_data => {
              if (_data.readin && cell.hasOwnProperty(_data.key)) {
                _data.value = cell[_data.key]
              }
            }
              return _data
            })
          }
            param.ID = primaryId || Utils.getguid()
            param.LText = Utils.getSysDefaultSql(btn, setting, formdata, param, data[0], columns, this.props.Tab) // 数据源
          if (btn.sqlType === 'insert') { // 系统函数添加时,生成uuid
            param.ID = Utils.getguid()
            param.LText = Utils.getSysDefaultSql(btn, setting, formdata, param, cell, columns, this.props.Tab, retmsg) // 数据源
            
            if (sessionStorage.getItem('dataM') === 'true') { // 数据权限
              param.LText = param.LText.replace(/\$@/ig, '/*')
@@ -289,24 +381,15 @@
            } else {
              param.LText = param.LText.replace(/@\$|\$@/ig, '')
            }
            param.LText = param.LText.replace(/\$check@|@check\$/ig, '')
            param.exec_type = 'y' // 后台解码
            param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
            param.secretkey = Utils.encrypt('', param.timestamp)
            if (/\$check@|@check\$/ig.test(param.LText)) {
              check_param = fromJS(param).toJS()
              check_param.LText = check_param.LText.replace(/\$check@/ig, '/*')
              check_param.LText = check_param.LText.replace(/@check\$/ig, '*/')
              check_param.LText = Utils.formatOptions(check_param.LText)
              param.LText = param.LText.replace(/\$check@|@check\$/ig, '')
            }
            param.LText = Utils.formatOptions(param.LText)
          } else if (btn.sql) {
          } else {
            param.ID = primaryId
            param.LText = Utils.getSysDefaultSql(btn, setting, formdata, param, data[0], columns, this.props.Tab) // 数据源
            param.LText = Utils.getSysDefaultSql(btn, setting, formdata, param, cell, columns, this.props.Tab, retmsg) // 数据源
            
            if (sessionStorage.getItem('dataM') === 'true') { // 数据权限
              param.LText = param.LText.replace(/\$@/ig, '/*')
@@ -314,202 +397,152 @@
            } else {
              param.LText = param.LText.replace(/@\$|\$@/ig, '')
            }
            param.LText = param.LText.replace(/\$check@|@check\$/ig, '')
            param.exec_type = 'y' // 后台解码
            param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
            param.secretkey = Utils.encrypt('', param.timestamp)
            if (/\$check@|@check\$/ig.test(param.LText)) {
              check_param = fromJS(param).toJS()
              check_param.LText = check_param.LText.replace(/\$check@/ig, '/*')
              check_param.LText = check_param.LText.replace(/@check\$/ig, '*/')
              check_param.LText = Utils.formatOptions(check_param.LText)
              param.LText = param.LText.replace(/\$check@|@check\$/ig, '')
            }
            param.LText = Utils.formatOptions(param.LText)
          }
        }
        if (this.props.menuType === 'HS' && param.timestamp) { // 函数 sPC_TableData_InUpDe 云端验证
          param.open_key = Utils.encryptOpenKey(param.secretkey, param.timestamp)
          if (check_param) {
            check_param.open_key = Utils.encryptOpenKey(check_param.secretkey, check_param.timestamp)
          }
        } else if (this.props.menuType === 'HS' && param.func === 's_sDataDictb_TBBack' && param.LTextOut) { // 函数 s_sDataDictb_TBBack 云端验证
          param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
          param.secretkey = Utils.encrypt(param.LTextOut, param.timestamp)
        if (this.props.menuType === 'HS') { // 函数 sPC_TableData_InUpDe 云端验证
          param.open_key = Utils.encryptOpenKey(param.secretkey, param.timestamp)
        }
        if (param.func === 'sPC_TableData_InUpDe') {
          param.menuname = btn.logLabel
          if (check_param) {
            check_param.menuname = btn.logLabel
          }
        }
        if (check_param) {
          this.setState({checkParam: check_param})
        }
        Api.genericInterface(param).then((res) => {
          if (res.status) {
            this.execSuccess(res)
          } else {
            this.execError(res)
          }
          _resolve()
        }, () => {
          this.updateStatus('over')
          _resolve()
        return param
      })
    }
    return _params
  }
  getInnerParam = (data, formdata) => {
    const { setting, btn } = this.props
    let _params = []
    if ( btn.Ot === 'notRequired' || btn.Ot === 'requiredSgl' || btn.Ot === 'requiredOnce' ) {
      let param = {
        func: btn.innerFunc
      }
      if (this.props.BID) {
        param.BID = this.props.BID
      }
      let primaryId = ''
      if (btn.Ot === 'requiredSgl' || btn.Ot === 'requiredOnce') {
        let ids = data.map(d => { return d[setting.primaryKey] || ''})
        ids = ids.filter(Boolean)
        primaryId = ids.join(',')
      }
      param[setting.primaryKey] = primaryId // 设置主键参数
      if (btn.OpenType === 'pop') { // 表单
        formdata.forEach(_data => {
          param[_data.key] = _data.value
        })
      } else if (btn.Ot === 'required') {
        let _formPrimaryId = ''
        if (formdata && setting.primaryKey) { // 表单中存在主键字段,主键值以表单中的值为准
          let _form = formdata.filter(_form => _form.key === setting.primaryKey)[0]
          if (_form) {
            _formPrimaryId = _form.value
          }
      }
      if (this.props.menuType === 'HS' && param.func === 's_sDataDictb_TBBack' && param.LTextOut) { // 函数 s_sDataDictb_TBBack 云端验证
        param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
        param.secretkey = Utils.encrypt(param.LTextOut, param.timestamp)
        param.open_key = Utils.encryptOpenKey(param.secretkey, param.timestamp)
      }
      _params.push(param)
    } else if (btn.Ot === 'required') {
      _params = data.map((cell, index) => {
        let param = {
          func: btn.innerFunc
        }
        let _params = data.map((cell, index) => {
          let param = {
            func: 'sPC_TableData_InUpDe'
        if (this.props.BID) {
          param.BID = this.props.BID
        }
        let primaryId = setting.primaryKey ? cell[setting.primaryKey] || '' : ''
        if (btn.OpenType === 'pop') { // 表单
          if (index !== 0) {
            formdata = formdata.map(_data => {
              if (_data.readin && cell.hasOwnProperty(_data.key)) {
                _data.value = cell[_data.key]
              }
              return _data
            })
          }
          if (this.props.BID) {
            param.BID = this.props.BID
          }
          formdata.forEach(_data => {
            param[_data.key] = _data.value
          })
        }
        param[setting.primaryKey] = primaryId
          let primaryId = setting.primaryKey ? cell[setting.primaryKey] || '' : ''
        if (this.props.menuType === 'HS' && param.func === 's_sDataDictb_TBBack' && param.LTextOut) { // 函数 s_sDataDictb_TBBack 云端验证
          param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
          param.secretkey = Utils.encrypt(param.LTextOut, param.timestamp)
          param.open_key = Utils.encryptOpenKey(param.secretkey, param.timestamp)
        }
          if (btn.OpenType === 'prompt' || btn.OpenType === 'exec') { // 是否弹框或直接执行
        return param
      })
    }
            if (btn.innerFunc) {
              param.func = btn.innerFunc
              if (setting.primaryKey) {
                param[setting.primaryKey] = primaryId
              }
            } else if (btn.sql) {
              param.ID = primaryId
              param.LText = Utils.getSysDefaultSql(btn, setting, '', param, cell, columns, this.props.Tab) // 数据源
              if (sessionStorage.getItem('dataM') === 'true') { // 数据权限
                param.LText = param.LText.replace(/\$@/ig, '/*')
                param.LText = param.LText.replace(/@\$/ig, '*/')
              } else {
                param.LText = param.LText.replace(/@\$|\$@/ig, '')
              }
              param.LText = param.LText.replace(/\$check@|@check\$/ig, '')
    return _params
  }
              param.exec_type = 'y' // 后台解码
              param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
              param.secretkey = Utils.encrypt('', param.timestamp)
              param.LText = Utils.formatOptions(param.LText)
            }
          } else if (btn.OpenType === 'pop') { // 表单
            if (index !== 0) {
              formdata = formdata.map(_data => {
                if (_data.readin && cell.hasOwnProperty(_data.key)) {
                  _data.value = cell[_data.key]
                }
                return _data
              })
            }
  /**
   * @description 按钮提交执行
   */
  execSubmit = (data, _resolve, formdata) => {
    const { setting, btn } = this.props
    if (btn.intertype === 'system' || btn.intertype === 'inner') { // 系统接口
      let params = []
            if (btn.innerFunc) {
              param.func = btn.innerFunc
      if (btn.intertype === 'system') {
        params = this.getSystemParam(data, formdata)
      } else {
        params = this.getInnerParam(data, formdata)
      }
              formdata.forEach(_data => {
                param[_data.key] = _data.value
              })
              if (setting.primaryKey) {
                param[setting.primaryKey] = primaryId
              }
            } else if (btn.sql && btn.sqlType === 'insert') { // 系统函数添加时,生成uuid
              param.ID = _formPrimaryId || Utils.getguid()
              param.LText = Utils.getSysDefaultSql(btn, setting, formdata, param, cell, columns, this.props.Tab) // 数据源
              if (sessionStorage.getItem('dataM') === 'true') { // 数据权限
                param.LText = param.LText.replace(/\$@/ig, '/*')
                param.LText = param.LText.replace(/@\$/ig, '*/')
              } else {
                param.LText = param.LText.replace(/@\$|\$@/ig, '')
              }
              param.LText = param.LText.replace(/\$check@|@check\$/ig, '')
              param.exec_type = 'y' // 后台解码
              param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
              param.secretkey = Utils.encrypt('', param.timestamp)
              param.LText = Utils.formatOptions(param.LText)
            } else if (btn.sql) {
              param.ID = primaryId
              param.LText = Utils.getSysDefaultSql(btn, setting, formdata, param, cell, columns, this.props.Tab) // 数据源
              if (sessionStorage.getItem('dataM') === 'true') { // 数据权限
                param.LText = param.LText.replace(/\$@/ig, '/*')
                param.LText = param.LText.replace(/@\$/ig, '*/')
              } else {
                param.LText = param.LText.replace(/@\$|\$@/ig, '')
              }
              param.LText = param.LText.replace(/\$check@|@check\$/ig, '')
              param.exec_type = 'y' // 后台解码
              param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
              param.secretkey = Utils.encrypt('', param.timestamp)
              param.LText = Utils.formatOptions(param.LText)
            }
          }
          if (this.props.menuType === 'HS' && param.timestamp) { // 函数 sPC_TableData_InUpDe 云端验证
            param.open_key = Utils.encryptOpenKey(param.secretkey, param.timestamp)
          } else if (this.props.menuType === 'HS' && param.func === 's_sDataDictb_TBBack' && param.LTextOut) { // 函数 s_sDataDictb_TBBack 云端验证
            param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
            param.secretkey = Utils.encrypt(param.LTextOut, param.timestamp)
            param.open_key = Utils.encryptOpenKey(param.secretkey, param.timestamp)
          }
          if (param.func === 'sPC_TableData_InUpDe') {
            param.menuname = btn.logLabel
          }
          return param
        })
        if (_params.length <= 20) {
          let deffers = _params.map(param => {
            return new Promise(resolve => {
              Api.genericInterface(param).then(res => {
                resolve(res)
              }, () => {
                this.updateStatus('over')
                _resolve()
              })
      if (params.length <= 20) {
        let deffers = params.map(param => {
          return new Promise(resolve => {
            Api.genericInterface(param).then(res => {
              resolve(res)
            }, () => {
              this.updateStatus('over')
              _resolve()
            })
          })
          Promise.all(deffers).then(result => {
            let iserror = false
            let errorMsg = ''
            result.forEach(res => {
              if (res.status) {
                errorMsg = res
              } else {
                iserror = true
                errorMsg = res
              }
            })
            if (!iserror) {
              this.execSuccess(errorMsg)
        })
        Promise.all(deffers).then(result => {
          let iserror = false
          let errorMsg = ''
          result.forEach(res => {
            if (res.status) {
              errorMsg = res
            } else {
              this.execError(errorMsg)
              iserror = true
              errorMsg = res
            }
            _resolve()
          })
        } else { // 超出20个请求时循环执行
          this.innerLoopRequest(_params, btn, _resolve)
        }
          if (!iserror) {
            this.execSuccess(errorMsg)
          } else {
            this.execError(errorMsg)
          }
          _resolve()
        })
      } else { // 超出20个请求时循环执行
        this.innerLoopRequest(params, btn, _resolve)
      }
    } else if (btn.intertype === 'outer') {
      /** *********************调用外部接口************************* */
@@ -571,15 +604,136 @@
      // 循环调用外部接口(包括内部及回调函数)
      this.outerLoopRequest(_params, btn, _resolve, _params.length > 20)
    } else if (btn.intertype === 'custom') { // 系统接口
      let params = []
      if (!btn.innerFunc) {
        params = this.getSystemParam(data, formdata, true)
        params = params.map(item => {
          item.script_type = 'Y'
          return item
        })
      } else {
        params = this.getInnerParam(data, formdata)
      }
      this.customLoopRequest(params, _resolve)
    }
  }
  /**
   * @description 自定义请求循环执行
   */
  customLoopRequest = (params, _resolve) => {
    let param = params.shift()
    this.setState({
      loadingNumber: params.length || ''
    })
    Api.genericInterface(param).then(res => {
      if (res.status) {
        if (res.mk_ex_invoke === 'false' && params.length === 0) {
          this.execSuccess(res)
          _resolve()
        } else if (res.mk_ex_invoke === 'false' && params.length > 0) {
          this.customLoopRequest(params, _resolve)
        } else {
          this.customOuterRequest(params, res, _resolve)
        }
      } else if (res.ErrCode === 'C' && this.state.checkParam) {
        const _this = this
        confirm({
          title: res.message || res.ErrMesg,
          content: '继续执行?',
          onOk() {
            return new Promise(resolve => {
              Api.genericInterface(_this.state.checkParam).then((result) => {
                if (result.status) {
                  if (result.mk_ex_invoke === 'false' && params.length === 0) {
                    _this.execSuccess(result)
                    _resolve()
                  } else if (result.mk_ex_invoke === 'false' && params.length > 0) {
                    _this.customLoopRequest(params, _resolve)
                  } else {
                    _this.customOuterRequest(params, result, _resolve)
                  }
                } else {
                  _this.execError(result)
                  _resolve()
                }
                resolve()
              }, () => {
                _this.updateStatus('over')
                resolve()
                _resolve()
              })
            })
          },
          onCancel() {
            _this.execError({...res, ErrCode: 'P'})
            _resolve()
          }
        })
        this.setState({checkParam: null})
      } else {
        this.execError(res)
        _resolve()
      }
    }, () => {
      this.updateStatus('over')
      _resolve()
    })
  }
  /**
   * @description 自定义请求循环执行
   */
  customOuterRequest = (params, result, _resolve) => {
    const { btn } = this.props
    let url = ''
    if (window.GLOB.systemType === 'production') {
      url = btn.proInterface
    } else {
      url = btn.interface
    }
    delete result.mk_ex_invoke
    delete result.status
    delete result.message
    delete result.ErrCode
    delete result.ErrMesg
    let param = {}
    Object.keys(result).forEach(key => {
      key = key.replace(/^mk_/ig, '')
      param[key] = result[key]
    })
    Api.directRequest(url, btn.method, param).then(res => {
      if (res.status) {
        if (params.length === 0) {
          this.execSuccess(res)
          _resolve()
        } else {
          this.customLoopRequest(params, btn, _resolve)
        }
      } else {
        this.execError(res)
        _resolve()
      }
    }, () => {
      this.updateStatus('over')
      _resolve()
    })
  }
  /**
   * @description 内部请求循环执行
   */
  innerLoopRequest = (params, btn, _resolve) => {
    if (!params && params.length === 0) return
    let param = params.shift()
    this.setState({
src/tabviews/zshare/mutilform/index.jsx
@@ -228,6 +228,10 @@
      if (['select', 'link', 'multiselect', 'radio', 'checkbox', 'checkcard'].includes(item.type) && item.resourceType === '1') {
        deForms.push(item)
      } else if (['select', 'link', 'radio'].includes(item.type) && item.resourceType !== '1') { // 选中第一项
        if (item.initval.indexOf('$first') > -1) {
          item.initval = item.options[0] ? item.options[0].Value : ''
        }
      }
      return item
@@ -449,6 +453,7 @@
        }
        return item
      })
      let values = []
      this.setState({
        formlist: _formlist.map(item => {
@@ -457,8 +462,21 @@
          } else if (['select', 'multiselect', 'radio', 'checkbox', 'checkcard'].includes(item.type)) {
            item.options = item.oriOptions
          }
          if (['select', 'link', 'radio'].includes(item.type) && item.initval.indexOf('$first') > -1) { // 选中第一项
            item.initval = item.options[0] ? item.options[0].Value : ''
            values.push({field: item.field, value: item.initval})
          }
          return item
        })
      }, () => {
        if (values.length === 0) return
        let fieldsvalue = {}
        values.forEach(item => {
          if (this.props.form.getFieldValue(item.field) !== undefined) {
            fieldsvalue[item.field] = item.value
          }
        })
        this.props.form.setFieldsValue(fieldsvalue)
      })
    })
  }
@@ -542,6 +560,7 @@
        }
        return item
      })
      let values = []
      this.setState({
        formlist: _formlist.map(item => {
@@ -550,8 +569,21 @@
          } else if (['select', 'multiselect', 'radio', 'checkbox', 'checkcard'].includes(item.type)) {
            item.options = item.oriOptions
          }
          if (['select', 'link', 'radio'].includes(item.type) && item.initval.indexOf('$first') > -1) { // 选中第一项
            item.initval = item.options[0] ? item.options[0].Value : ''
            values.push({field: item.field, value: item.initval})
          }
          return item
        })
      }, () => {
        if (values.length === 0) return
        let fieldsvalue = {}
        values.forEach(item => {
          if (this.props.form.getFieldValue(item.field) !== undefined) {
            fieldsvalue[item.field] = item.value
          }
        })
        this.props.form.setFieldsValue(fieldsvalue)
      })
    })
  }
@@ -621,30 +653,18 @@
    }
    if (subfields.length === 0) {
      if (Object.keys(fieldsvalue).length > 0) {
        this.props.form.setFieldsValue(fieldsvalue)
      }
      if (Object.keys(_record).length > 0) {
        this.setState({
          record: {...record, ..._record}
        })
      }
      this.props.form.setFieldsValue(fieldsvalue)
      this.setState({
        record: {...record, ..._record}
      })
    } else {
      let result = this.resetform(formlist, subfields, 0, fieldsvalue)
      if (Object.keys(result.fieldsvalue).length > 0) {
        this.props.form.setFieldsValue(fieldsvalue)
      }
      let _param = {
        formlist: result.formlist
      }
      if (Object.keys(_record).length > 0) {
        _param.record = {...record, ..._record}
      }
      this.setState(_param)
      this.props.form.setFieldsValue(fieldsvalue)
      this.setState({
        formlist: result.formlist,
        record: {...record, ..._record}
      })
    }
    this.setState({}, () => {
src/templates/calendarconfig/tabcomponent/tabform/index.jsx
@@ -23,9 +23,9 @@
  UNSAFE_componentWillMount () {
    const { formlist } = this.props
    let type = formlist.filter(cell => cell.key === 'type')[0].initVal
    // let type = formlist.filter(cell => cell.key === 'type')[0].initVal
    let _tabs = this.props.tabs.filter(tab => tab.type === type)
    let _tabs = this.props.tabs.filter(tab => tab.type === 'SubTable')
    this.setState({
      formlist: formlist.map(item => {
@@ -247,6 +247,7 @@
          if (!values.linkTab) { // 没有关联标签(新建时),创建新标签Id
            values.linkTab = Utils.getuuid()
          }
          values.type = 'SubTable' // 类型为子表
          resolve(values)
        } else {
src/templates/sharecomponent/actioncomponent/actionform/index.jsx
@@ -69,6 +69,19 @@
    }, {
      value: 'custom',
      text: this.props.dict['header.form.custom']
    }],
    interTypeOptions: [{
      value: 'system',
      text: this.props.dict['model.interface.system']
    }, {
      value: 'inner',
      text: this.props.dict['model.interface.inner']
    }, {
      value: 'outer',
      text: this.props.dict['model.interface.outer']
    }, {
      value: 'custom',
      text: '自定义'
    }]
  }
@@ -77,7 +90,7 @@
    const { card } = this.props
    let _opentype = card.OpenType               // 打开方式
    let _tabType = card.tabType || 'SubTable'   // 按钮为弹窗(标签)时,标签的类型
    // let _tabType = card.tabType || 'SubTable'   // 按钮为弹窗(标签)时,标签的类型
    let _intertype = card.intertype || 'system' // 接口类型
    let _funcType = card.funcType || ''         // 功能按钮默认类型
    let _tabTemplate = card.tabTemplate         // 按钮为标签页时,标签类型:三级菜单或表单标签页
@@ -90,7 +103,7 @@
      _opentype = 'tab'
    }
    let _tabs = this.props.tabs.filter(tab => tab.type === _tabType)
    let _tabs = this.props.tabs.filter(tab => tab.type === 'SubTable')
    let _options = this.getOptions(_opentype, _intertype, _funcType, _pageTemplate, _tabTemplate)
    
    this.setState({
@@ -104,6 +117,9 @@
          item.options = btnClasses
        } else if (item.key === 'icon') {
          item.options = btnIcons
        } else if (item.key === 'intertype') {
          let iscustom = ['pop', 'prompt', 'exec'].includes(_opentype)
          item.options = this.state.interTypeOptions.filter(op => (iscustom || op.value !== 'custom'))
        } else if (item.key === 'Ot') {
          if (card.position === 'grid' || _pageTemplate === 'pay') { // 行级按钮、支付按钮,只能选单行
            item.options = this.state.requireOptions.filter(op => ['requiredSgl'].includes(op.value))
@@ -188,7 +204,9 @@
        }
      }
    } else if (_opentype !== 'popview') { // 打开方式不是弹窗页面时
      if (_intertype === 'outer') {
      if (_intertype === 'custom') {
        _options.push('sql', 'sqlType', 'innerFunc', 'interface', 'callbackType', 'cbTable', 'proInterface', 'method')
      } else if (_intertype === 'outer') {
        _options.push('innerFunc', 'sysInterface', 'interface', 'outerFunc', 'callbackFunc')
      } else if (_intertype === 'inner') {
        _options.push('innerFunc')
@@ -205,24 +223,27 @@
  }
  /**
   * @description 下拉切换
   * 1、打开方式切换,重置可见表单和表单值
   * 2、显示位置切换,重置选择行
   * 3、切换标签类型,重置可选标签
   * @description 切换
   */
  openTypeChange = (key, value) => {
  optionChange = (key, value) => {
    const { openType, funcType } = this.state
    const { card } = this.props
    if (key === 'OpenType') {
      let _options = this.getOptions(value, this.state.interType, this.state.funcType, this.state.pageTemplate, card.tabTemplate)
      let _options = this.getOptions(value, 'system', '', this.state.pageTemplate, card.tabTemplate)
      let _fieldval = {}
      let _formlist = this.state.formlist.map(item => {
        item.hidden = !_options.includes(item.key)
        if (item.key === 'intertype') {
          let iscustom = ['pop', 'prompt', 'exec'].includes(value)
          item.options = this.state.interTypeOptions.filter(op => (iscustom || op.value !== 'custom'))
        }
        if (item.hidden) return item
        if (item.key === 'intertype') {
          _fieldval.intertype = this.state.interType
          _fieldval.intertype = 'system'
        } else if (item.key === 'Ot') {
          if (this.state.position === 'grid' || this.state.pageTemplate === 'pay') {
            item.options = this.state.requireOptions.filter(op => ['requiredSgl'].includes(op.value))
@@ -253,6 +274,8 @@
      this.setState({
        openType: value,
        funcType: '',
        intertype: 'system',
        formlist: _formlist
      }, () => {
        if (value === 'excelIn') {
@@ -275,10 +298,10 @@
            if (value === 'grid' || this.state.pageTemplate === 'pay') {
              item.options = this.state.requireOptions.filter(op => ['requiredSgl'].includes(op.value))
              _fieldval.Ot = 'requiredSgl'
            } else if (this.state.openType === 'innerpage' && this.state.pageTemplate === 'billprint') {
            } else if (openType === 'innerpage' && this.state.pageTemplate === 'billprint') {
              item.options = this.state.requireOptions.filter(op => ['notRequired', 'requiredSgl', 'required'].includes(op.value))
              _fieldval.Ot = 'requiredSgl'
            } else if (['innerpage', 'blank', 'tab', 'popview'].includes(this.state.openType)) {
            } else if (['innerpage', 'blank', 'tab', 'popview'].includes(openType)) {
              item.options = this.state.requireOptions.filter(op => ['notRequired', 'requiredSgl'].includes(op.value))
              _fieldval.Ot = 'requiredSgl'
            } else {
@@ -290,26 +313,26 @@
      }, () => {
        this.props.form.setFieldsValue(_fieldval)
      })
    } else if (key === 'tabType') {
      let _tabs = this.props.tabs.filter(tab => tab.type === value)
      let _fieldval = {}
    // } else if (key === 'tabType') {
    //   let _tabs = this.props.tabs.filter(tab => tab.type === value)
    //   let _fieldval = {}
      this.setState({
        formlist: this.state.formlist.map(item => {
          if (item.key === 'linkTab') {
            item.options = [
              {
                value: '',
                text: '新建'
              },
              ..._tabs
            ]
          }
          return item
        })
      }, () => {
        this.props.form.setFieldsValue(_fieldval)
      })
    //   this.setState({
    //     formlist: this.state.formlist.map(item => {
    //       if (item.key === 'linkTab') {
    //         item.options = [
    //           {
    //             value: '',
    //             text: '新建'
    //           },
    //           ..._tabs
    //         ]
    //       }
    //       return item
    //     })
    //   }, () => {
    //     this.props.form.setFieldsValue(_fieldval)
    //   })
    } else if (key === 'funcType') {
      let _options = this.getOptions('funcbutton', this.state.interType, value, card.pageTemplate, card.tabTemplate)
      let _fieldval = {}
@@ -405,14 +428,7 @@
          return item
        })
      })
    }
  }
  onChange = (e, key) => {
    const { openType, funcType } = this.state
    let value = e.target.value
    if (key === 'intertype') {
    } else if (key === 'intertype') {
      let _options = this.getOptions(openType, value, funcType, '', '')
      this.setState({
@@ -560,7 +576,7 @@
                <Select
                  showSearch
                  filterOption={(input, option) => option.props.children[2].toLowerCase().indexOf(input.toLowerCase()) >= 0}
                  onChange={(value) => {this.openTypeChange(item.key, value)}}
                  onChange={(value) => {this.optionChange(item.key, value)}}
                  getPopupContainer={() => document.getElementById('winter')}
                >
                  {item.options.map((option, index) =>
@@ -586,7 +602,7 @@
                  }
                ]
              })(
                <Radio.Group onChange={(e) => {this.onChange(e, item.key)}} disabled={item.readonly}>
                <Radio.Group onChange={(e) => {this.optionChange(item.key, e.target.value)}} disabled={item.readonly}>
                  {
                    item.options.map(option => {
                      return (
src/templates/sharecomponent/actioncomponent/actionform/index.scss
@@ -12,6 +12,12 @@
      width: 86%;
    }
  }
  .ant-radio-group {
    white-space: nowrap;
    .ant-radio-wrapper {
      margin-right: 4px;
    }
  }
  .ant-input-number {
    width: 100%;
  }
src/templates/sharecomponent/actioncomponent/index.jsx
@@ -887,7 +887,7 @@
        <Modal
          title={dict['model.action'] + '-' + (card && card.copyType === 'action' ? dict['model.copy'] : dict['model.edit'])}
          visible={visible}
          width={800}
          width={850}
          maskClosable={false}
          onCancel={this.editModalCancel}
          footer={[
src/templates/sharecomponent/tabscomponent/tabform/index.jsx
@@ -26,9 +26,9 @@
  UNSAFE_componentWillMount () {
    const { formlist } = this.props
    let type = formlist.filter(cell => cell.key === 'type')[0].initVal
    // let type = formlist.filter(cell => cell.key === 'type')[0].initVal
    let _tabs = this.props.tabs.filter(tab => tab.type === type)
    let _tabs = this.props.tabs.filter(tab => tab.type === 'SubTable')
    this.setState({
      formlist: formlist.map(item => {
@@ -281,6 +281,8 @@
            return
          }
          values.type = 'SubTable' // 类型为子表
          resolve(values)
        } else {
          reject(err)
src/templates/zshare/formconfig.jsx
@@ -723,23 +723,6 @@
      label: Formdict['header.form.intertype'],
      initVal: card.intertype || 'system',
      required: true,
      options: [{
        value: 'system',
        text: Formdict['model.interface.system']
      }, {
        value: 'inner',
        text: Formdict['model.interface.inner']
      }, {
        value: 'outer',
        text: Formdict['model.interface.outer']
      }]
    },
    {
      type: 'select',
      key: 'sqlType',
      label: Formdict['header.form.action.type'],
      initVal: card.sqlType || '',
      required: true,
      options: []
    },
    {
@@ -748,6 +731,14 @@
      label: Formdict['model.form.tablename'],
      initVal: card.sql || config.setting.tableName || '',
      required: true
    },
    {
      type: 'radio',
      key: 'sqlType',
      label: Formdict['header.form.action.type'],
      initVal: card.sqlType || '',
      required: true,
      options: []
    },
    {
      type: 'text',
@@ -768,17 +759,17 @@
      required: card.intertype === 'inner',
      readonly: false
    },
    {
      type: 'select',
      key: 'tabType',
      label: Formdict['model.form.tabType'],
      initVal: card.tabType || 'SubTable',
      required: true,
      options: [{
        value: 'SubTable',
        text: Formdict['model.menu.tab.subtable']
      }]
    },
    // {
    //   type: 'select',
    //   key: 'tabType',
    //   label: Formdict['model.form.tabType'],
    //   initVal: card.tabType || 'SubTable',
    //   required: true,
    //   options: [{
    //     value: 'SubTable',
    //     text: Formdict['model.menu.tab.subtable']
    //   }]
    // },
    {
      type: 'select',
      key: 'linkTab',
@@ -856,6 +847,50 @@
      readonly: card.sysInterface === 'true'
    },
    {
      type: 'radio',
      key: 'method',
      label: '请求方式',
      initVal: card.method || 'post',
      required: true,
      options: [{
        value: 'get',
        text: 'GET'
      }, {
        value: 'post',
        text: 'POST'
      }]
    },
    {
      type: 'text',
      key: 'proInterface',
      label: '正式地址',
      initVal: card.proInterface || '',
      tooltip: '正式系统所使用的接口地址。',
      required: false
    },
    {
      type: 'radio',
      key: 'callbackType',
      label: '回调方式',
      initVal: card.callbackType || 'default',
      tooltip: '使用默认方式执行时,需要配合计划任务。',
      required: true,
      options: [{
        value: 'default',
        text: '默认执行'
      }, {
        value: 'script',
        text: '自定义脚本'
      }]
    },
    {
      type: 'text',
      key: 'cbTable',
      label: '回调表名',
      initVal: card.cbTable || '',
      required: true
    },
    {
      type: 'text',
      key: 'callbackFunc',
      label: Formdict['header.form.callbackFunc'],
@@ -864,7 +899,7 @@
      readonly: false
    },
    {
      type: 'select',
      type: 'radio',
      key: 'position',
      label: Formdict['header.form.position'],
      initVal: card.position || 'toolbar',
@@ -1939,7 +1974,7 @@
      type: 'text',
      key: 'initval',
      label: Formdict['header.form.initval'],
      tooltip: '下拉多选与多选框,添加多个初始值请使用“,”号分隔。',
      tooltip: '下拉多选与多选框,添加多个初始值请使用“,”号分隔。注:下拉选择、联动菜单或单选框中$first表示选择第一项',
      initVal: card.initval || '',
      required: false
    },
@@ -1956,14 +1991,14 @@
      key: 'openVal',
      label: '开启值',
      initVal: card.openVal || '',
      required: true
      required: false
    },
    {
      type: 'text',
      key: 'closeVal',
      label: '关闭值',
      initVal: card.closeVal || '',
      required: true
      required: false
    },
    {
      type: 'text',
@@ -2466,17 +2501,17 @@
      initVal: card.label || '',
      required: true
    },
    {
      type: 'select',
      key: 'type',
      label: Formdict['model.form.tabType'],
      initVal: card.type || 'SubTable',
      required: true,
      options: [{
        value: 'SubTable',
        text: Formdict['model.menu.tab.subtable']
      }]
    },
    // {
    //   type: 'select',
    //   key: 'type',
    //   label: Formdict['model.form.tabType'],
    //   initVal: card.type || 'SubTable',
    //   required: true,
    //   options: [{
    //     value: 'SubTable',
    //     text: Formdict['model.menu.tab.subtable']
    //   }]
    // },
    {
      type: 'select',
      key: 'linkTab',
src/templates/zshare/verifycard/callbackcustomscript/index.jsx
New file
@@ -0,0 +1,273 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import { Form, Row, Col, Button, notification, Modal, Tooltip, Icon, Radio, Select } from 'antd'
import moment from 'moment'
import Utils from '@/utils/utils.js'
import Api from '@/api'
import CodeMirror from '@/templates/zshare/codemirror'
import './index.scss'
class CustomForm extends Component {
  static propTpyes = {
    dict: PropTypes.object,         // 字典项
    btn: PropTypes.object,          // 按钮信息
    systemScripts: PropTypes.array, // 系统脚本
    customScripts: PropTypes.array, // 自定义脚本
    scriptsChange: PropTypes.func   // 表单
  }
  state = {
    editItem: null,
    loading: false
  }
  edit = (record) => {
    this.setState({
      editItem: record
    })
    this.props.form.setFieldsValue({
      sql: record.sql,
      position: record.position || 'back'
    })
  }
  handleConfirm = () => {
    const { editItem } = this.state
    // 表单提交时检查输入值是否正确
    this.props.form.validateFieldsAndScroll((err, values) => {
      if (!err) {
        values.uuid = editItem ? editItem.uuid : ''
        let _quot = values.sql.match(/'{1}/g)
        let _lparen = values.sql.match(/\({1}/g)
        let _rparen = values.sql.match(/\){1}/g)
        _quot = _quot ? _quot.length : 0
        _lparen = _lparen ? _lparen.length : 0
        _rparen = _rparen ? _rparen.length : 0
        if (_quot % 2 !== 0) {
          notification.warning({
            top: 92,
            message: 'sql中\'必须成对出现',
            duration: 5
          })
          return
        } else if (_lparen !== _rparen) {
          notification.warning({
            top: 92,
            message: 'sql中()必须成对出现',
            duration: 5
          })
          return
        } else if (/--/ig.test(values.sql)) {
          notification.warning({
            top: 92,
            message: '自定义sql语句中,不可出现字符 -- ,注释请用 /*内容*/',
            duration: 5
          })
          return
        }
        let error = Utils.verifySql(values.sql, 'customscript')
        if (error) {
          notification.warning({
            top: 92,
            message: 'sql中不可使用' + error,
            duration: 5
          })
          return
        }
        let tail = `
          aaa:
        `
        let _prevCustomScript = '' // 默认sql前执行脚本
        let _backCustomScript = '' // 默认sql后执行脚本
        this.props.customScripts.forEach(item => {
          if (item.status === 'false') return
          if (item.position === 'front') {
            _prevCustomScript += `
            /* 默认sql前脚本 */
            ${values.uuid === item.uuid ? values.sql : item.sql}
            `
          } else {
            _backCustomScript += `
            /* 默认sql后脚本 */
            ${values.uuid === item.uuid ? values.sql : item.sql}
            `
          }
        })
        let param = {
          func: 's_debug_sql',
          exec_type: 'y',
          LText: _prevCustomScript + _backCustomScript + tail
        }
        // 数据权限
        param.LText = param.LText.replace(/@\$|\$@/ig, '')
        // check
        param.LText = param.LText.replace(/\$check@|@check\$/ig, '')
        // 外联数据库替换
        if (window.GLOB.externalDatabase !== null) {
          param.LText = param.LText.replace(/@db@/ig, window.GLOB.externalDatabase)
        }
        console.info(`/* sql 验证 */\n${param.LText.replace(/\n\s{6,20}/ig, '\n')}`)
        param.LText = Utils.formatOptions(param.LText)
        param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
        param.secretkey = Utils.encrypt('', param.timestamp)
        this.setState({loading: true})
        Api.getLocalConfig(param).then(res => {
          if (res.status) {
            this.setState({
              loading: false,
              editItem: null
            }, () => {
              this.props.scriptsChange(values)
            })
            this.props.form.setFieldsValue({
              sql: ' '
            })
          } else {
            this.setState({loading: false})
            Modal.error({
              title: res.message
            })
          }
        })
      }
    })
  }
  handleCancel = () => {
    this.setState({
      editItem: null
    })
    this.props.form.setFieldsValue({
      sql: ' '
    })
  }
  selectScript = (value, option) => {
    let _sql = this.props.form.getFieldValue('sql')
    if (_sql) {
      _sql = _sql + `
      `
    }
    _sql = _sql.replace(/\s{6}$/, '')
    _sql = _sql + `/*${option.props.children}*/
    `
    _sql = _sql.replace(/\s{4}$/, '')
    _sql = _sql + value
    this.props.form.setFieldsValue({
      sql: _sql
    })
  }
  render() {
    const { systemScripts, btn } = this.props
    const { getFieldDecorator } = this.props.form
    const formItemLayout = {
      labelCol: {
        xs: { span: 24 },
        sm: { span: 8 }
      },
      wrapperCol: {
        xs: { span: 24 },
        sm: { span: 16 }
      }
    }
    return (
      <Form {...formItemLayout} className="verify-form" id="verify-custom-scripts">
        <Row gutter={24}>
          {btn.cbTable ? <Col span={8}>
            <Form.Item label={'表名'} style={{whiteSpace: 'nowrap', margin: 0}}>
              {btn.cbTable}
            </Form.Item>
          </Col> : null}
          <Col span={16}>
            <Form.Item label={'报错字段'} style={{margin: 0}}>
              ErrorCode, retmsg
            </Form.Item>
          </Col>
          <Col span={8} style={{whiteSpace: 'nowrap'}}>
            <Form.Item style={{marginBottom: 0}} label={
              <Tooltip placement="bottomLeft" title={'自定义脚本与默认sql位置关系。'}>
                <Icon type="question-circle" style={{color: '#c49f47', marginRight: '5px'}} />
                执行位置
              </Tooltip>
            }>
              {getFieldDecorator('position', {
                initialValue: 'front'
              })(
                <Radio.Group>
                  <Radio value="front">sql前</Radio>
                  <Radio value="back">sql后</Radio>
                </Radio.Group>
              )}
            </Form.Item>
          </Col>
          <Col span={10}>
            <Form.Item label={'快捷添加'} style={{marginBottom: 0}}>
              <Select
                showSearch
                filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0}
                onChange={this.selectScript}
                getPopupContainer={() => document.getElementById('verify-custom-scripts')}
              >
                {systemScripts.map((option, i) =>
                  <Select.Option key={i} value={option.value}>{option.name}</Select.Option>
                )}
              </Select>
            </Form.Item>
          </Col>
          <Col span={6} className="add">
            <Button onClick={this.handleConfirm} loading={this.state.loading} className="mk-green" style={{marginBottom: 15, marginLeft: 40}}>
              保存
            </Button>
            <Button onClick={this.handleCancel} style={{marginBottom: 15, marginLeft: 10}}>
              取消
            </Button>
          </Col>
          <Col span={24} className="sql">
            <Form.Item label={
              <Tooltip placement="topLeft" title={'数据检查替换符 $check@ -> /* 或 \'\'、 @check$ -> */ 或 \'\''}>
                <Icon type="question-circle" />
                sql
              </Tooltip>
            }>
              {getFieldDecorator('sql', {
                initialValue: '',
                rules: [
                  {
                    required: true,
                    message: this.props.dict['form.required.input'] + 'sql!'
                  }
                ]
              })(<CodeMirror />)}
            </Form.Item>
          </Col>
        </Row>
      </Form>
    )
  }
}
export default Form.create()(CustomForm)
src/templates/zshare/verifycard/callbackcustomscript/index.scss
New file
@@ -0,0 +1,5 @@
#verify-custom-scripts {
  .ant-select-dropdown-menu-item {
    white-space: normal;
  }
}
src/templates/zshare/verifycard/index.jsx
@@ -11,6 +11,7 @@
import ContrastForm from './contrastform'
import CustomForm from './customform'
import CustomScript from './customscript'
import CallBackCustomScript from './callbackcustomscript'
import BillcodeForm from './billcodeform'
import VoucherForm from './voucherform'
import asyncComponent from '@/utils/asyncComponent'
@@ -355,6 +356,73 @@
          </div>)
      }
    ],
    cbScriptsColumns: [
      {
        title: 'SQL',
        dataIndex: 'sql',
        width: '60%',
        render: (text) => {
          let title = text.match(/^\s*\/\*.+\*\//)
          title = title && title[0] ? title[0] : ''
          text = title ? text.replace(title, '') : text
          return (
            <div>
              {title ? <span style={{color: '#a50'}}>{title}</span> : null}
              <Paragraph copyable ellipsis={{ rows: 4, expandable: true }}>{text}</Paragraph>
            </div>
          )
        }
      },
      {
        title: '执行位置',
        dataIndex: 'position',
        width: '10%',
        render: (text, record) => {
          if (record.position === 'front') {
            return 'sql前'
          } else {
            return 'sql后'
          }
        }
      },
      {
        title: '状态',
        dataIndex: 'status',
        width: '10%',
        render: (text, record) => record.status === 'false' ?
          (
            <div>
              {this.props.dict['model.status.forbidden']}
              <Icon style={{marginLeft: '5px'}} type="stop" theme="twoTone" twoToneColor="#ff4d4f" />
            </div>
          ) :
          (
            <div>
              {this.props.dict['model.status.open']}
              <Icon style={{marginLeft: '5px'}} type="check-circle" theme="twoTone" twoToneColor="#52c41a" />
            </div>
          )
      },
      {
        title: '操作',
        align: 'center',
        width: '20%',
        dataIndex: 'operation',
        render: (text, record) =>
          (<div style={{textAlign: 'center'}}>
            <span className="operation-btn" title={this.props.dict['model.edit']} onClick={() => this.handleEdit(record, 'cbscripts')} style={{color: '#1890ff'}}><Icon type="edit" /></span>
            <span className="operation-btn" title={this.props.dict['header.form.status.change']} onClick={() => this.handleStatus(record, 'cbscripts')} style={{color: '#8E44AD'}}><Icon type="swap" /></span>
            <Popconfirm
              overlayClassName="popover-confirm"
              title={this.props.dict['model.query.delete']}
              onConfirm={() => this.handleDelete(record, 'cbscripts')
            }>
              <span className="operation-btn" style={{color: '#ff4d4f'}}><Icon type="delete" /></span>
            </Popconfirm>
          </div>)
      }
    ],
    orderColumns: [
      {
        title: this.props.dict['header.form.funcvar'],
@@ -485,10 +553,15 @@
    _verify.billcodes = _verify.billcodes || []
    _verify.voucher = _verify.voucher || {enabled: false}
    _verify.scripts = _verify.scripts || []
    _verify.cbScripts = _verify.cbScripts || []
    this.setState({
      verify: _verify
    })
    if (config.Template !== 'FormTab' && (card.intertype === 'inner' || card.intertype === 'outer')) { // 内部或外部接口
      return
    }
    new Promise(resolve => {
      let _fields = []
@@ -523,11 +596,7 @@
            }
            
            if (!_LongParam) {
              notification.warning({
                top: 92,
                message: '未获取到表单信息,部分验证将无法设置!',
                duration: 5
              })
              message.warning('未获取到表单信息,部分验证将无法设置!')
            } else {
              if (_LongParam.groups.length > 0) {
                _LongParam.groups.forEach(group => {
@@ -989,6 +1058,25 @@
    this.setState({ verify })
  }
  cbScriptsChange = (values) => {
    let verify = fromJS(this.state.verify).toJS()
    if (values.uuid) {
      verify.cbScripts = verify.cbScripts.map(item => {
        if (item.uuid === values.uuid) {
          return values
        } else {
          return item
        }
      })
    } else {
      values.uuid = Utils.getuuid()
      verify.cbScripts.push(values)
    }
    this.setState({ verify })
  }
  orderChange = (values) => {
    let verify = fromJS(this.state.verify).toJS()
@@ -1050,6 +1138,8 @@
      verify.billcodes = verify.billcodes.filter(item => item.uuid !== record.uuid)
    } else if (type === 'scripts') {
      verify.scripts = verify.scripts.filter(item => item.uuid !== record.uuid)
    } else if (type === 'cbscripts') {
      verify.cbScripts = verify.cbScripts.filter(item => item.uuid !== record.uuid)
    }
    this.setState({ verify })
@@ -1062,6 +1152,8 @@
      this.orderForm.edit(record)
    } else if (type === 'scripts') {
      this.scriptsForm.edit(record)
    } else if (type === 'cbscripts') {
      this.cbscriptsForm.edit(record)
    }
    let node = document.getElementById('verify-card-box-tab').parentNode
@@ -1102,6 +1194,14 @@
      })
    } else if (type === 'scripts') {
      verify.scripts = verify.scripts.map(item => {
        if (item.uuid === record.uuid) {
          return record
        } else {
          return item
        }
      })
    } else if (type === 'cbscripts') {
      verify.cbScripts = verify.cbScripts.map(item => {
        if (item.uuid === record.uuid) {
          return record
        } else {
@@ -1267,7 +1367,7 @@
  render() {
    const { card } = this.props
    const { verify, fields, uniqueFields, uniqueColumns, unionFields, onceUniqueColumns, columnsFields, contrastColumns, customColumns, orderColumns, scriptsColumns, orderModular, orderModularDetail, voucher, voucherDetail, notes } = this.state
    const { verify, fields, uniqueFields, uniqueColumns, unionFields, onceUniqueColumns, columnsFields, contrastColumns, customColumns, orderColumns, scriptsColumns, cbScriptsColumns, orderModular, orderModularDetail, voucher, voucherDetail, notes } = this.state
    const formItemLayout = {
      labelCol: {
        xs: { span: 24 },
@@ -1281,7 +1381,7 @@
    return (
      <div id="verify-card-box-tab">
        {card.intertype === 'system' ? <Tabs defaultActiveKey="1" className="verify-card-box">
        {card.intertype === 'system' || card.intertype === 'custom' ? <Tabs defaultActiveKey="1" className="verify-card-box">
          <TabPane tab="基础验证" key="1">
            <Form {...formItemLayout}>
              <Row gutter={24}>
@@ -1482,6 +1582,22 @@
            />
            <EditTable actions={['move']} data={verify.scripts} columns={scriptsColumns} onChange={(scripts) => {this.setState({verify: {...verify, scripts}})}}/>
          </TabPane>
          {card.callbackType === 'script' && card.intertype === 'custom' ? <TabPane tab={
            <span>
              回调脚本
              {verify.cbScripts.length ? <span className="count-tip">{verify.cbScripts.length}</span> : null}
            </span>
          } key="6a">
            <CallBackCustomScript
              dict={this.props.dict}
              btn={this.props.card}
              customScripts={verify.cbScripts}
              systemScripts={this.state.systemScripts}
              scriptsChange={this.cbScriptsChange}
              wrappedComponentRef={(inst) => this.cbscriptsForm = inst}
            />
            <EditTable actions={['move']} data={verify.cbScripts} columns={cbScriptsColumns} onChange={(cbScripts) => {this.setState({verify: {...verify, cbScripts}})}}/>
          </TabPane> : null}
          <TabPane tab="信息提示" key="7">
            <Form {...formItemLayout}>
              <Row gutter={24}>
@@ -1570,7 +1686,7 @@
            </Form>
          </TabPane>
        </Tabs> : null}
        {card.intertype !== 'system' ? <Tabs defaultActiveKey="7" className="verify-card-box">
        {card.intertype !== 'system' && card.intertype !== 'custom' ? <Tabs defaultActiveKey="7" className="verify-card-box">
          <TabPane tab="信息提示" key="7">
            <Form {...formItemLayout}>
              <Row gutter={24}>
src/utils/utils.js
@@ -1055,7 +1055,7 @@
   * @return {String} type   执行类型
   * @return {String} table  表名
   */
  static getSysDefaultSql (btn, setting, formdata, param, data, columns, tab) {
  static getSysDefaultSql (btn, setting, formdata, param, data, columns, tab, retmsg) {
    let primaryId = param.ID
    let BID = param.BID
    let verify = btn.verify || {}
@@ -1689,8 +1689,14 @@
      _sql += _backCustomScript
    }
    _sql += `
        aaa: select @ErrorCode as ErrorCode,@retmsg as retmsg`
    if (retmsg) {
      _sql += `
          aaa: if @ErrorCode!=''
          insert into tmp_err_retmsg (ID, ErrorCode, retmsg, CreateUserID) select @time_id@,@ErrorCode, @retmsg,@UserID@`
    } else {
      _sql += `
          aaa: select @ErrorCode as ErrorCode,@retmsg as retmsg`
    }
    if ((window.GLOB.systemType !== 'production' && options.sysType !== 'cloud') || window.debugger === true) {
      _sql = _sql.replace(/\n\s{8}/ig, '\n')