king
8 天以前 a1e9b18a4dbfd21e1bf4d5cb60974ac2f0115efd
src/tabviews/zshare/actionList/normalbutton/index.jsx
@@ -3,7 +3,7 @@
import moment from 'moment'
import qs from 'qs'
import { is, fromJS } from 'immutable'
import { Button, Modal, notification, message, Drawer, Switch, Checkbox, Progress } from 'antd'
import { Button, Modal, notification, message, Popover, Drawer, Switch, Checkbox, Progress } from 'antd'
import md5 from 'md5'
import Api from '@/api'
@@ -13,7 +13,8 @@
import MKEmitter from '@/utils/events.js'
import MkIcon from '@/components/mk-icon'
import MkCounter from './mkcounter'
// import './index.scss'
import './index.scss'
const MutilForm = asyncSpinComponent(() => import('@/tabviews/zshare/mutilform'))
const { confirm } = Modal
@@ -28,6 +29,7 @@
    columns: PropTypes.any,           // 字段列
    setting: PropTypes.any,           // 页面通用设置
    disabled: PropTypes.any,          // 行按钮禁用
    name: PropTypes.any
  }
  state = {
@@ -43,10 +45,12 @@
    hidden: false,
    autoMatic: false,
    check: false,
    count: 0
    count: 0,
    dict: window.GLOB.dict,
    submitType: ''
  }
  moduleParams = null
  preCallback = null
  UNSAFE_componentWillMount () {
    const { btn, selectedData, BData, disabled } = this.props
@@ -180,33 +184,17 @@
  }
  actionSubmit = (res) => {
    const { btn, setting, BID } = this.props
    const { btn } = this.props
    const { selines } = this.state
    if (btn.uuid !== res.menuId) return
    let data = selines || []
    if (setting.supModule && !BID) {
      notification.warning({
        top: 92,
        message: '需要上级主键值!',
        duration: 3
      })
      return
    } else if (btn.Ot !== 'notRequired' && data.length === 0) {
      notification.warning({
        top: 92,
        message: '请选择行!',
        duration: 5
      })
      return
    } else if (btn.Ot === 'requiredSgl' && data.length !== 1) {
      notification.warning({
        top: 92,
        message: '请选择单行数据!',
        duration: 5
      })
    let valid = this.checkBtnData(data)
    if (!valid) {
      this.preCallback && this.preCallback()
      return
    }
@@ -214,122 +202,36 @@
    this.execSubmit(data, () => {}, res.form)
  }
  /**
   * @description 按钮状态改变
   */
  updateStatus = () => {
    this.setState({
      loading: false,
      visible: false,
      confirmLoading: false
    })
  }
  
  /**
   * @description 触发按钮操作
   */
  actionTrigger = (triggerId, record, type) => {
    const { BID, btn, selectedData, setting } = this.props
    const { loading, disabled } = this.state
  actionTrigger = (triggerId, record, type, lid, callback) => {
    const { btn, selectedData, LID } = this.props
    const { loading, disabled, dict } = this.state
    if (type === 'preButton') {
      if (btn.uuid !== triggerId) return
      this.preTrigger(callback)
      return
    } else {
      this.preCallback = null
    }
    if (loading || disabled) return
    if (triggerId && btn.uuid !== triggerId) return
    if (setting.supModule && !BID) {
      notification.warning({
        top: 92,
        message: '需要上级主键值!',
        duration: 5
      })
      return
    } else if (type === 'linkbtn' && !btn.$toolbtn && !is(fromJS(selectedData || []), fromJS(record))) {
      return
    }
    if (type === 'linkbtn' && !btn.$toolbtn && LID !== lid) return
    if (btn.OpenType === 'form' && btn.formType === 'count_line') return
    this.setState({autoMatic: type === 'autoMatic'})
    let _this = this
    let that = this
    let data = record || selectedData || []
    if (btn.Ot !== 'notRequired' && data.length === 0) {
      // 需要选择行时,校验数据
      notification.warning({
        top: 92,
        message: '请选择行!',
        duration: 5
      })
      return
    } else if (btn.Ot === 'requiredSgl' && data.length !== 1) {
      // 需要选择单行时,校验数据
      notification.warning({
        top: 92,
        message: '请选择单行数据!',
        duration: 5
      })
      return
    } else if (btn.intertype === 'system') {
      // 使用内部接口时,操作类型和数据源不可为空
      if (!btn.sql || !btn.sqlType) {
        notification.warning({
          top: 92,
          message: '按钮操作类型错误!',
          duration: 5
        })
        return
      } else if (data.length === 0 && btn.verify && btn.verify.voucher && btn.verify.voucher.enabled) {
        notification.warning({
          top: 92,
          message: '使用创建凭证函数,需要选择行!',
          duration: 5
        })
        return
      }
    } else if (btn.intertype === 'inner') {
      // 使用内部接口时,内部函数不可为空
      if (!btn.innerFunc) {
        notification.warning({
          top: 92,
          message: '按钮内部函数不可为空!',
          duration: 5
        })
        return
      }
    } else if (btn.intertype === 'custom' || btn.intertype === 'outer') {
      if (btn.callbackType === 'script' && (!btn.verify || !btn.verify.cbScripts || !btn.verify.cbScripts.filter(item => item.status !== 'false').length === 0)) {
        notification.warning({
          top: 92,
          message: '使用自定义脚本回调时,回调脚本不可为空!',
          duration: 5
        })
        return
      } else if (btn.procMode === 'system' && data.length === 0 && btn.verify && btn.verify.voucher && btn.verify.voucher.enabled) {
        notification.warning({
          top: 92,
          message: '使用创建凭证函数,需要选择行!',
          duration: 5
        })
        return
      } else if (btn.intertype === 'custom' && window.GLOB.systemType === 'production' && !btn.proInterface) {
        notification.warning({
          top: 92,
          message: '尚未设置正式系统接口地址!',
          duration: 5
        })
        return
      }
    } else if (!['inner', 'outer', 'system', 'custom'].includes(btn.intertype)) {
      if (btn.OpenType === 'form' && btn.formType === 'count_line') {
        return
      }
      // 接口类型错误
      notification.warning({
        top: 92,
        message: '按钮接口类型错误!',
        duration: 5
      })
      return
    }
    let valid = this.checkBtnData(data)
    if (!valid) return
    this.setState({
      selines: data
@@ -339,18 +241,19 @@
      this.setState({}, () => {
        MKEmitter.emit('mkFormSubmit', btn.uuid)
      })
      return
    } else if (btn.OpenType === 'prompt') {
      this.setState({loading: true})
      confirm({
        title: btn.tipTitle || '确定要执行吗?',
        title: btn.tipTitle || dict['exec_sure'] || '确定要执行吗?',
        okText: dict['ok'] || '确定',
        cancelText: dict['cancel'] || '取消',
        onOk() {
          return new Promise(resolve => {
            _this.execSubmit(data, resolve)
            that.execSubmit(data, resolve)
          })
        },
        onCancel() {
          _this.setState({loading: false})
          that.setState({loading: false})
        }
      })
    } else if (btn.OpenType === 'exec') {
@@ -410,14 +313,148 @@
      let _change = {
        prompt: '提示框',
        exec: '直接执行',
        pop: '弹窗(表单)'
        pop: '弹窗(表单)',
        formSubmit: '表单',
        form: '表单',
      }
      MKEmitter.emit('queryTrigger', {menuId: btn.uuid, name: _change[btn.OpenType]})
    }
  }
  preTrigger = (callback) => {
    const { btn, selectedData } = this.props
    const { loading, disabled, dict } = this.state
    if (loading || disabled) {
      callback()
      return
    } else if (btn.OpenType === 'form') {
      callback()
      return
    }
    let that = this
    let data = selectedData || []
    let valid = this.checkBtnData(data)
    if (!valid) {
      callback()
      return
    }
    this.preCallback = callback
    this.setState({
      selines: data
    })
    if (btn.OpenType === 'formSubmit') {
      this.setState({}, () => {
        MKEmitter.emit('mkFormSubmit', btn.uuid, callback)
      })
    } else if (btn.OpenType === 'prompt') {
      this.setState({loading: true})
      confirm({
        title: btn.tipTitle || dict['exec_sure'] || '确定要执行吗?',
        okText: dict['ok'] || '确定',
        cancelText: dict['cancel'] || '取消',
        onOk() {
          return new Promise(resolve => {
            that.execSubmit(data, resolve)
          })
        },
        onCancel() {
          callback()
          that.setState({loading: false})
        }
      })
    } else if (btn.OpenType === 'exec') {
      this.setState({loading: true})
      this.execSubmit(data, () => { this.setState({loading: false})})
    } else if (btn.OpenType === 'pop') {
      let modal = this.state.btnconfig
      if (!modal && btn.modal) {
        modal = this.handleModelConfig(btn.modal)
      }
      this.setState({
        loading: true,
        btnconfig: modal
      })
      if (modal) {
        if (modal.setting.display === 'prompt' || modal.setting.display === 'exec') {
          this.modelconfirm()
        } else {
          this.setState({
            visible: true
          })
        }
      }
    }
  }
  /**
   * @description 按钮状态改变
   */
  updateStatus = () => {
    this.setState({
      loading: false,
      visible: false,
      confirmLoading: false
    })
  }
  checkBtnData = (data) => {
    const { BID, btn, setting } = this.props
    const { dict } = this.state
    if (setting.supModule && !BID) {
      notification.warning({
        top: 92,
        message: setting.supModTip || dict['sup_key_req'] || '需要上级主键值!',
        duration: 5
      })
      return false
    } else if (btn.Ot !== 'notRequired' && data.length === 0) {
      // 需要选择行时,校验数据
      notification.warning({
        top: 92,
        message: dict['select_row'] || '请选择行!',
        duration: 5
      })
      return false
    } else if (btn.Ot !== 'notRequired' && data[0] && !data[0].$$uuid) {
      notification.warning({
        top: 92,
        message: dict['id_required'] || '未获取到ID值!',
        duration: 5
      })
      return false
    } else if (btn.Ot === 'requiredSgl' && data.length !== 1) {
      // 需要选择单行时,校验数据
      notification.warning({
        top: 92,
        message: dict['select_single_row'] || '请选择单行数据!',
        duration: 5
      })
      return false
    } else if (btn.intertype === 'custom' && window.GLOB.systemType === 'production' && !btn.proInterface) {
      notification.warning({
        top: 92,
        message: dict['no_prod_link'] || '尚未设置正式系统接口地址!',
        duration: 5
      })
      return false
    }
    return true
  }
  getSystemParam = (data, formdata, retmsg) => {
    const { setting, columns, btn } = this.props
    const { submitType } = this.state
    let _params = []
    if ( btn.Ot === 'notRequired' || btn.Ot === 'requiredSgl' || btn.Ot === 'requiredOnce' ) {
@@ -431,8 +468,8 @@
      
      let primaryId = ''
      if ((btn.Ot === 'requiredSgl' || btn.Ot === 'requiredOnce') && setting.primaryKey) {
        let ids = data.map(d => { return d[setting.primaryKey] || ''})
      if (btn.Ot === 'requiredSgl' || btn.Ot === 'requiredOnce') {
        let ids = data.map(d => d.$$uuid)
        ids = ids.filter(Boolean)
        primaryId = ids.join(',')
      }
@@ -441,17 +478,17 @@
        param.ID = primaryId
        if (retmsg) {
          const { sql, callbacksql } = getSysDefaultSql(btn, setting, '', param, data[0], columns, retmsg, this.moduleParams, Utils.getAllSearchOptions) // 数据源
          const { sql, callbacksql } = getSysDefaultSql(btn, setting, '', param, data[0], columns, retmsg, submitType) // 数据源
          param.LText = sql
          param.$callbacksql = callbacksql
        } else {
          param.LText = getSysDefaultSql(btn, setting, '', param, data[0], columns, false, this.moduleParams, Utils.getAllSearchOptions) // 数据源
          param.LText = getSysDefaultSql(btn, setting, '', param, data[0], columns, false, submitType) // 数据源
          if (btn.output) {
            param.key_back_type = 'Y'
          }
        }
        param.exec_type = 'y' // 后台解码
        param.exec_type = window.GLOB.execType || 'y' // 后台解码
        param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
        param.secretkey = Utils.encrypt('', param.timestamp)
@@ -462,32 +499,23 @@
          param.LText = param.LText.replace(/\$check@|@check\$/ig, '')
        }
        param.LText = Utils.formatOptions(param.LText)
        param.LText = Utils.formatOptions(param.LText, param.exec_type)
      } else if (btn.OpenType === 'pop' || btn.OpenType === 'formSubmit' || btn.OpenType === 'form') { // 表单
        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.ID = Utils.getguid()
          if (retmsg) {
            const { sql, callbacksql } = getSysDefaultSql(btn, setting, formdata, param, data[0], columns, retmsg, this.moduleParams, Utils.getAllSearchOptions) // 数据源
            const { sql, callbacksql } = getSysDefaultSql(btn, setting, formdata, param, data[0], columns, retmsg, submitType) // 数据源
            param.LText = sql
            param.$callbacksql = callbacksql
          } else {
            param.LText = getSysDefaultSql(btn, setting, formdata, param, data[0], columns, false, this.moduleParams, Utils.getAllSearchOptions) // 数据源
            param.LText = getSysDefaultSql(btn, setting, formdata, param, data[0], columns, false, submitType) // 数据源
            if (btn.output) {
              param.key_back_type = 'Y'
            }
          }
          param.exec_type = 'y' // 后台解码
          param.exec_type = window.GLOB.execType || 'y' // 后台解码
          param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
          param.secretkey = Utils.encrypt('', param.timestamp)
@@ -498,22 +526,22 @@
            param.LText = param.LText.replace(/\$check@|@check\$/ig, '')
          }
          param.LText = Utils.formatOptions(param.LText)
          param.LText = Utils.formatOptions(param.LText, param.exec_type)
        } else {
          param.ID = primaryId
          if (retmsg) {
            const { sql, callbacksql } = getSysDefaultSql(btn, setting, formdata, param, data[0], columns, retmsg, this.moduleParams, Utils.getAllSearchOptions) // 数据源
            const { sql, callbacksql } = getSysDefaultSql(btn, setting, formdata, param, data[0], columns, retmsg, submitType) // 数据源
            param.LText = sql
            param.$callbacksql = callbacksql
          } else {
            param.LText = getSysDefaultSql(btn, setting, formdata, param, data[0], columns, false, this.moduleParams, Utils.getAllSearchOptions) // 数据源
            param.LText = getSysDefaultSql(btn, setting, formdata, param, data[0], columns, false, submitType) // 数据源
            if (btn.output) {
              param.key_back_type = 'Y'
            }
          }
          param.exec_type = 'y' // 后台解码
          param.exec_type = window.GLOB.execType || 'y' // 后台解码
          param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
          param.secretkey = Utils.encrypt('', param.timestamp)
@@ -524,7 +552,7 @@
            param.LText = param.LText.replace(/\$check@|@check\$/ig, '')
          }
          param.LText = Utils.formatOptions(param.LText)
          param.LText = Utils.formatOptions(param.LText, param.exec_type)
        }
      }
@@ -544,7 +572,7 @@
      if (param.$unCheckParam) {
        param.$unCheckParam.LText = param.$unCheckParam.LText.replace(/\$check@/ig, '/*').replace(/@check\$/ig, '*/')
        param.$unCheckParam.LText = Utils.formatOptions(param.$unCheckParam.LText)
        param.$unCheckParam.LText = Utils.formatOptions(param.$unCheckParam.LText, param.exec_type)
        param.$unCheckParam.menuname = btn.logLabel
        if (window.GLOB.probation) {
@@ -569,17 +597,17 @@
          param.ID = primaryId
          if (retmsg) {
            const { sql, callbacksql } = getSysDefaultSql(btn, setting, '', param, cell, columns, retmsg, this.moduleParams, Utils.getAllSearchOptions) // 数据源
            const { sql, callbacksql } = getSysDefaultSql(btn, setting, '', param, cell, columns, retmsg, submitType) // 数据源
            param.LText = sql
            param.$callbacksql = callbacksql
          } else {
            param.LText = getSysDefaultSql(btn, setting, '', param, cell, columns, false, this.moduleParams, Utils.getAllSearchOptions) // 数据源
            param.LText = getSysDefaultSql(btn, setting, '', param, cell, columns, false, submitType) // 数据源
            if (btn.output) {
              param.key_back_type = 'Y'
            }
          }
          param.exec_type = 'y' // 后台解码
          param.exec_type = window.GLOB.execType || 'y' // 后台解码
          param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
          param.secretkey = Utils.encrypt('', param.timestamp)
@@ -590,7 +618,7 @@
            param.LText = param.LText.replace(/\$check@|@check\$/ig, '')
          }
          param.LText = Utils.formatOptions(param.LText)
          param.LText = Utils.formatOptions(param.LText, param.exec_type)
        } else if (btn.OpenType === 'pop') { // 表单
          if (index !== 0) {
            let _cell = {}
@@ -609,17 +637,17 @@
            param.ID = Utils.getguid()
            if (retmsg) {
              const { sql, callbacksql } = getSysDefaultSql(btn, setting, formdata, param, cell, columns, retmsg, this.moduleParams, Utils.getAllSearchOptions) // 数据源
              const { sql, callbacksql } = getSysDefaultSql(btn, setting, formdata, param, cell, columns, retmsg, submitType) // 数据源
              param.LText = sql
              param.$callbacksql = callbacksql
            } else {
              param.LText = getSysDefaultSql(btn, setting, formdata, param, cell, columns, false, this.moduleParams, Utils.getAllSearchOptions) // 数据源
              param.LText = getSysDefaultSql(btn, setting, formdata, param, cell, columns, false, submitType) // 数据源
              if (btn.output) {
                param.key_back_type = 'Y'
              }
            }
            param.exec_type = 'y' // 后台解码
            param.exec_type = window.GLOB.execType || 'y' // 后台解码
            param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
            param.secretkey = Utils.encrypt('', param.timestamp)
@@ -630,22 +658,22 @@
              param.LText = param.LText.replace(/\$check@|@check\$/ig, '')
            }
            param.LText = Utils.formatOptions(param.LText)
            param.LText = Utils.formatOptions(param.LText, param.exec_type)
          } else {
            param.ID = primaryId
            if (retmsg) {
              const { sql, callbacksql } = getSysDefaultSql(btn, setting, formdata, param, cell, columns, retmsg, this.moduleParams, Utils.getAllSearchOptions) // 数据源
              const { sql, callbacksql } = getSysDefaultSql(btn, setting, formdata, param, cell, columns, retmsg, submitType) // 数据源
              param.LText = sql
              param.$callbacksql = callbacksql
            } else {
              param.LText = getSysDefaultSql(btn, setting, formdata, param, cell, columns, false, this.moduleParams, Utils.getAllSearchOptions) // 数据源
              param.LText = getSysDefaultSql(btn, setting, formdata, param, cell, columns, false, submitType) // 数据源
              if (btn.output) {
                param.key_back_type = 'Y'
              }
            }
            param.exec_type = 'y' // 后台解码
            param.exec_type = window.GLOB.execType || 'y' // 后台解码
            param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
            param.secretkey = Utils.encrypt('', param.timestamp)
@@ -656,7 +684,7 @@
              param.LText = param.LText.replace(/\$check@|@check\$/ig, '')
            }
            param.LText = Utils.formatOptions(param.LText)
            param.LText = Utils.formatOptions(param.LText, param.exec_type)
          }
        }
@@ -675,7 +703,7 @@
        if (param.$unCheckParam) {
          param.$unCheckParam.LText = param.$unCheckParam.LText.replace(/\$check@/ig, '/*').replace(/@check\$/ig, '*/')
          param.$unCheckParam.LText = Utils.formatOptions(param.$unCheckParam.LText)
          param.$unCheckParam.LText = Utils.formatOptions(param.$unCheckParam.LText, param.exec_type)
          param.$unCheckParam.menuname = btn.logLabel
  
          if (window.GLOB.probation) {
@@ -688,6 +716,478 @@
    }
    return _params
  }
  getBackSystemParam = (data, formdata) => {
    const { btn } = this.props
    let ex = window.GLOB.CacheData.get('sql_' + btn.uuid)
    let _params = []
    if (btn.Ot === 'notRequired' || btn.Ot === 'requiredSgl' || btn.Ot === 'requiredOnce') {
      let primaryId = ''
      let cell = null
      if (btn.Ot === 'requiredSgl' || btn.Ot === 'requiredOnce') {
        primaryId = data.map(d => d.$$uuid).filter(Boolean).join(',')
        cell = data[0]
      }
      if (btn.OpenType === 'pop' || btn.OpenType === 'formSubmit' || btn.OpenType === 'form') { // 表单
        if (btn.sqlType === 'insert') { // 系统函数添加时,生成uuid
          primaryId = Utils.getguid()
        }
      }
      let exp = this.getExps(ex, formdata, cell, primaryId, btn.$process)
      if (ex.reps.includes('mk_check_begin')) {
        exp.$unCheckParam = fromJS(exp).toJS()
        exp.data[0].exps.push({
          key: 'mk_check_begin',
          value: ''
        }, {
          key: 'mk_check_end',
          value: ''
        })
        exp.$unCheckParam.data[0].exps.push({
          key: 'mk_check_begin',
          value: 'Y'
        }, {
          key: 'mk_check_end',
          value: 'Y'
        })
      } else if (btn.procMode === 'system' && btn.callbackType === 'script') {
        let _backex = window.GLOB.CacheData.get('sql_back_' + btn.uuid)
        exp.$backParam = this.getExps(_backex, formdata, cell, primaryId)
      }
      _params.push(exp)
    } else if (btn.Ot === 'required') {
      _params = data.map((cell, index) => {
        let primaryId = cell.$$uuid || ''
        if (btn.OpenType === 'pop') { // 表单
          if (index !== 0) {
            let _cell = {}
            Object.keys(cell).forEach(key => {
              _cell[key.toLowerCase()] = cell[key]
            })
            formdata = formdata.map(_data => {
              if (_data.readin && _cell.hasOwnProperty(_data.key.toLowerCase())) {
                _data.value = _cell[_data.key.toLowerCase()]
              }
              return _data
            })
          }
          if (btn.sqlType === 'insert') { // 系统函数添加时,生成uuid
            primaryId = Utils.getguid()
          }
        }
        let exp = this.getExps(ex, formdata, cell, primaryId, btn.$process)
        if (ex.reps.includes('mk_check_begin')) {
          exp.$unCheckParam = fromJS(exp).toJS()
          exp.data[0].exps.push({
            key: 'mk_check_begin',
            value: ''
          }, {
            key: 'mk_check_end',
            value: ''
          })
          exp.$unCheckParam.data[0].exps.push({
            key: 'mk_check_begin',
            value: 'Y'
          }, {
            key: 'mk_check_end',
            value: 'Y'
          })
        } else if (btn.procMode === 'system' && btn.callbackType === 'script') {
          let _backex = window.GLOB.CacheData.get('sql_back_' + btn.uuid)
          exp.$backParam = this.getExps(_backex, formdata, cell, primaryId)
        }
        return exp
      })
    }
    return _params
  }
  getExps = (ex, formdata, cell, id, process) => {
    const { columns, BID, btn } = this.props
    const { submitType } = this.state
    let exps = []
    let values = {
      time_id: Utils.getguid(),
      roleid: sessionStorage.getItem('role_id') || '',
      mk_departmentcode: sessionStorage.getItem('departmentcode') || '',
      mk_organization: sessionStorage.getItem('organization') || '',
      mk_user_type: sessionStorage.getItem('mk_user_type') || '',
      mk_nation: sessionStorage.getItem('nation') || '',
      mk_province: sessionStorage.getItem('province') || '',
      mk_city: sessionStorage.getItem('city') || '',
      mk_district: sessionStorage.getItem('district') || '',
      mk_address: sessionStorage.getItem('address') || '',
      id: id || '',
      bid: BID || '',
      typename: 'admin',
      datam: sessionStorage.getItem('dataM') === 'true' ? 'Y' : '',
      datam_begin: sessionStorage.getItem('dataM') === 'true' ? 'Y' : '',
      datam_end: sessionStorage.getItem('dataM') === 'true' ? 'Y' : '',
      mk_submit_type: submitType || ''
      // mk_check_begin: '',
      // mk_check_end: ''
    }
    if (window.GLOB.externalDatabase !== null) {
      values.db = window.GLOB.externalDatabase
    }
    let formkeys = []
    formdata && formdata.forEach(form => {
      formkeys.push(form.key)
      let val = form.value
      if (form.type === 'number' || form.type === 'rate') {
        if (isNaN(val) || val === '') {
          val = 0
        }
      } else if (['date', 'datemonth'].includes(form.type)) {
        val = val || '1949-10-01'
      }
      exps.push({
        key: 'mk_' + form.key + '_mk',
        value: val
      })
    })
    if (cell && columns && columns.length > 0) {
      let datavars = {}
      Object.keys(cell).forEach(key => {
        datavars[key.toLowerCase()] = cell[key]
      })
      columns.forEach(col => {
        if (!ex.reps.includes(col.field) || formkeys.includes(col.field)) return
        if (!col.datatype) return
        let _key = col.field.toLowerCase()
        let _val = datavars.hasOwnProperty(_key) ? datavars[_key] : ''
        if (/^date/ig.test(col.datatype) && !_val) {
          _val = '1949-10-01'
        }
        exps.push({
          key: 'mk_' + col.field + '_mk',
          value: _val
        })
      })
    }
    ex.reps.forEach(n => {
      let key = n.toLowerCase()
      if (values.hasOwnProperty(key)) {
        exps.push({
          key: n,
          value: values[key]
        })
      }
    })
    if (btn.verify && btn.verify.printEnable === 'true' && !btn.output && !ex.reps.includes('ID') && values.id) {
      exps.push({
        key: 'ID',
        value: values.id
      })
    }
    if (process && btn.verify.workFlow === 'true') {
      let flow = window.GLOB.UserCacheMap.get(btn.$flowId)
      let node = null
      let line = null
      let target = null
      let status = 0
      let statusName = ''
      let detailId = ''
      let sign = ''
      let error = ''
      let userid = sessionStorage.getItem('UserID') || ''
      let checkIds = []
      let checkUsers = []
      let noticeIds = []
      let work_grade = sessionStorage.getItem('work_grade') || 0
      let departmentcode = sessionStorage.getItem('departmentcode') || ''
      let _data = cell || {}
      let msg = ''
      if (btn.verify.flowType === 'start') {
        target = flow ? flow.cells.filter(cell => cell.mknode === 'start')[0] : ''
        if (target) {
          detailId = target.id
          status = target.mkdata.status
          statusName = target.mkdata.statusName
        } else {
          error = '工作流无开始节点'
        }
      } else if (_data.works_flow_param) {
        try {
          node = JSON.parse(window.decodeURIComponent(window.atob(_data.works_flow_param)))
        } catch (e) {
          node = null
        }
        if (node) {
          let lines = flow ? flow.cells.filter(cell => cell.shape === 'edge' && cell.source.cell === node.id) : []
          if (btn.verify.flowType === 'reject') {
            line = lines.filter(cell => cell.mkdata.flowType === 'reject' || cell.mknode === 'startEdge')[0]
          } else {
            lines = lines.filter(cell => cell.mkdata.flowType !== 'reject' && cell.mknode !== 'startEdge')
            if (lines.length === 0) {
              error = '无可执行的流程分支'
            } else {
              let branchKey = btn.verify.flowBranch ? btn.verify.flowBranch.toLowerCase() : ''
              formdata && formdata.forEach(form => {
                let _key = form.key.toLowerCase()
                _data[_key] = form.value
              })
              if (!branchKey) {
                lines.forEach(line => {
                  if (line.mkdata.execCondition === 'open') {
                    error = '按钮未设置流程控制字段。'
                  }
                })
                if (!error) {
                  lines = lines.filter(cell => {
                    if (cell.mkdata.seniorCondition === 'open' && !line) {
                      cell.mkdata.seniorbers && cell.mkdata.seniorbers.forEach(per => {
                        if (per.worker_id === userid) {
                          line = cell
                        }
                      })
                      return false
                    }
                    return true
                  })
                  if (!line) {
                    line = lines[0]
                  }
                }
              } else if (!_data.hasOwnProperty(branchKey)) {
                error = '信息中无流程控制字段。'
              } else {
                let _def_lines = []
                let _equ_lines = []
                let _unequ_lines = []
                let _or_lines = []
                let branchVal = _data[branchKey]
                if (branchVal && typeof(branchVal) === 'string' && !isNaN(branchVal)) {
                  branchVal = +branchVal
                }
                lines.forEach(item => {
                  if (item.mkdata.execCondition !== 'open') {
                    _def_lines.push(item)
                  } else {
                    if (item.mkdata.match === '=') {
                      if (item.mkdata.matchVal === branchVal + '') {
                        _equ_lines.push(item)
                      }
                    } else if (item.mkdata.match === '!=') {
                      if (item.mkdata.matchVal !== branchVal + '') {
                        _unequ_lines.push(item)
                      }
                    } else {
                      if (item.mkdata.match === '<') {
                        if (item.mkdata.matchVal < branchVal) {
                          _or_lines.push({...item, dist: Math.abs(item.mkdata.matchVal - branchVal)})
                        }
                      } else if (item.mkdata.match === '>') {
                        if (item.mkdata.matchVal > branchVal) {
                          _or_lines.push({...item, dist: Math.abs(item.mkdata.matchVal - branchVal)})
                        }
                      } else if (item.mkdata.match === '<=') {
                        if (item.mkdata.matchVal <= branchVal) {
                          _or_lines.push({...item, dist: Math.abs(item.mkdata.matchVal - branchVal)})
                        }
                      } else if (item.mkdata.match === '>=') {
                        if (item.mkdata.matchVal >= branchVal) {
                          _or_lines.push({...item, dist: Math.abs(item.mkdata.matchVal - branchVal)})
                        }
                      }
                    }
                  }
                })
                _or_lines.sort((a, b) => a.dist - b.dist)
                let _lines = [..._equ_lines, ..._or_lines, ..._unequ_lines, ..._def_lines]
                _lines = _lines.filter(cell => {
                  if (cell.mkdata.seniorCondition === 'open' && !line) {
                    cell.mkdata.seniorbers && cell.mkdata.seniorbers.forEach(per => {
                      if (per.worker_id === userid) {
                        line = cell
                      }
                    })
                    return false
                  }
                  return true
                })
                if (!line) {
                  line = _lines[0]
                }
              }
            }
          }
        } else {
          error = '行信息中工作流参数无法解析'
        }
        if (line) {
          detailId = line.id
          status = line.mkdata.status
          statusName = line.mkdata.statusName
          sign = line.mkdata.seniorSign || ''
          target = flow.cells.filter(cell => cell.id === line.target.cell)[0]
          line.mkdata.members && line.mkdata.members.forEach(item => {
            if (line.mkdata.approver === 'departmentManager') {
              if (item.job_type === 'manage' && departmentcode === item.parentIds[1]) {
                checkIds.push(item.worker_id)
                checkUsers.push(item)
              }
            } else if (line.mkdata.approver === 'directManager') {
              if (departmentcode === item.parentIds[1] && item.work_grade > work_grade) {
                checkIds.push(item.worker_id)
                checkUsers.push(item)
              }
            } else {
              checkIds.push(item.worker_id)
              checkUsers.push(item)
            }
          })
          line.mkdata.copys && line.mkdata.copys.forEach(item => {
            noticeIds.push(item.worker_id)
          })
          if (!target) {
            error = '未查询到工作流目标节点'
          } else if (checkIds.length === 0 && !['startEdge', 'endEdge', 'throughEdge'].includes(line.mknode)) {
            error = '未获取到下一步审批人'
          } else if (line.approvalMethod === 'countersign' && (!node.checkIds || !node.checkIds.includes(userid))) {
            error = '当前用户不在审批人列表中'
          }
        } else if (!error) {
          error = '工作流中无对应流程'
        }
      } else {
        error = '行信息中无工作流参数'
      }
      if (!error && btn.verify.flowSql !== 'true' && btn.verify.flowType !== 'start' && line && line.approvalMethod === 'countersign') {
        error = '会签流程需要使用默认脚本'
      }
      if (error) {
        status = 0
        statusName = '异常'
      } else if (target) {
        let label = target.attrs && target.attrs.text && target.attrs.text.text ? target.attrs.text.text : ''
        msg = {...target.mkdata, label: label, id: target.id, checkIds: [], checkUsers: []}
        msg = window.btoa(window.encodeURIComponent(JSON.stringify(msg)))
      }
      if (btn.verify.flowType === 'start') {
        exps.push(
          { key: 'works_flow_error', value: error },
          { key: 'works_flow_code', value: flow ? flow.flow_code : '' },
          { key: 'works_flow_name', value: flow ? flow.flow_name : '' },
          { key: 'works_flow_param', value: msg },
          { key: 'works_flow_detail_id', value: detailId },
          { key: 'status', value: status },
          { key: 'statusname', value: statusName },
          { key: 'work_group', value: sessionStorage.getItem('work_group') || '' },
          { key: 'work_grade', value: sessionStorage.getItem('work_grade') || 0 },
          // { key: 'start_type', value: '开始' },
        )
      } else {
        let works_flow_countersign = ''
        let works_flow_sign_values = ''
        let works_flow_sign_field = 'statuscharone'
        let works_flow_sign_label = ''
        let works_begin_branch = ''
        if (line) {
          if (line.approvalMethod === 'countersign' && node.checkIds.length > 1) {
            works_flow_countersign = 'Y'
            let mark = line.mark || '已审核'
            let fields = ['statuscharone', 'statuschartwo', 'statuscharthree', 'statuscharfour', 'statuscharfive']
            node.checkUsers.forEach((user, index) => {
              if (user.worker_id === userid) {
                works_flow_sign_field = fields[index]
                works_flow_sign_label = `${user.parentNames[2] || ''}${user.workername || ''}${mark}`
              } else {
                works_flow_sign_values += `${user.parentNames[2] || ''}${user.workername || ''}${mark}`
              }
            })
          } else {
            works_begin_branch = line.mknode === 'startEdge' ? 'Y' : ''
          }
        }
        exps.push(
          { key: 'works_flow_error', value: error },
          { key: 'works_flow_countersign', value: works_flow_countersign },
          { key: 'works_flow_sign_values', value: works_flow_sign_values },
          { key: 'works_begin_branch', value: works_begin_branch },
          { key: 'works_flow_sign_field', value: works_flow_sign_field },
          { key: 'works_flow_sign_label', value: works_flow_sign_label },
          { key: 'works_flow_code', value: flow ? flow.flow_code : '' },
          { key: 'works_flow_name', value: flow ? flow.flow_name : '' },
          { key: 'works_flow_param', value: msg },
          { key: 'works_flow_detail_id', value: detailId },
          { key: 'status', value: status },
          { key: 'statusname', value: statusName },
          { key: 'work_group', value: sessionStorage.getItem('work_group') || '' },
          { key: 'work_grade', value: sessionStorage.getItem('work_grade') || 0 },
          // { key: 'check_type', value: btn.verify.flowType === 'reject' ? '驳回' : '审核' },
          // { key: 'notice_type', value: '抄送' },
          { key: 'check_userids', value: checkIds.join(',') },
          { key: 'notice_userids', value: noticeIds.join(',') },
          { key: 'works_flow_sign', value: sign },
        )
      }
    }
    let md5_id = ''
    if (window.GLOB.probation) {
      md5_id = md5(ex.id + JSON.stringify(exps) + Math.floor(new Date().getTime() / 600000))
      md5_id = moment().format('YYYYMMDDHHmmss') + md5_id.slice(-18)
    }
    return {
      $backend: true,
      $type: 's_TableData_InUpDe',
      data: [{
        id: ex.id,
        menuname: btn.logLabel || '',
        exps: exps,
        md5_id: md5_id
      }]
    }
  }
  getInnerParam = (data, formdata, retmsg) => {
@@ -709,11 +1209,14 @@
        param.username = sessionStorage.getItem('User_Name') || ''
        param.fullname = sessionStorage.getItem('Full_Name') || ''
      }
      if (btn.dataM === 'true') {
        param.dataM = sessionStorage.getItem('dataM') === 'true' ? 'Y' : ''
      }
      
      let primaryId = ''
      if ((btn.Ot === 'requiredSgl' || btn.Ot === 'requiredOnce') && setting.primaryKey) {
        let ids = data.map(d => { return d[setting.primaryKey] || ''})
        let ids = data.map(d => d.$$uuid)
        ids = ids.filter(Boolean)
        primaryId = ids.join(',')
@@ -732,7 +1235,10 @@
        param.open_key = Utils.encryptOpenKey(param.secretkey, param.timestamp)
      }
      if (retmsg) {
      if (btn.callbackType === 'script' && window.backend && window.GLOB.CacheData.has('sql_back_' + btn.uuid)) {
        let _backex = window.GLOB.CacheData.get('sql_back_' + btn.uuid)
        param.$backParam = this.getExps(_backex, formdata, data[0], primaryId)
      } else if (retmsg) {
        param.$callbacksql = this.getSysDeclareSql(btn, formdata, data[0], columns, this.props.BID)
      }
@@ -751,8 +1257,11 @@
          param.username = sessionStorage.getItem('User_Name') || ''
          param.fullname = sessionStorage.getItem('Full_Name') || ''
        }
        if (btn.dataM === 'true') {
          param.dataM = sessionStorage.getItem('dataM') === 'true' ? 'Y' : ''
        }
        let primaryId = setting.primaryKey ? cell[setting.primaryKey] || '' : ''
        let primaryId = cell.$$uuid || ''
        if (btn.OpenType === 'pop') { // 表单
          if (index !== 0) {
@@ -782,7 +1291,10 @@
          param.open_key = Utils.encryptOpenKey(param.secretkey, param.timestamp)
        }
        if (retmsg) {
        if (btn.callbackType === 'script' && window.backend && window.GLOB.CacheData.has('sql_back_' + btn.uuid)) {
          let _backex = window.GLOB.CacheData.get('sql_back_' + btn.uuid)
          param.$backParam = this.getExps(_backex, formdata, cell, primaryId)
        } else if (retmsg) {
          param.$callbacksql = this.getSysDeclareSql(btn, formdata, cell, columns, this.props.BID)
        }
@@ -797,9 +1309,10 @@
   * @description 获取回调脚本的字段定义
   */
  getSysDeclareSql = (btn, formdata, data, columns, BID = '') => {
    let datavars = {}                 // 声明的变量,表单及显示列
    const { submitType } = this.state
    // 需要声明的变量集
    let _vars = ['tbid', 'errorcode', 'retmsg', 'billcode', 'bvoucher', 'fibvoucherdate', 'fiyear', 'username', 'fullname', 'modulardetailcode', 'roleid', 'mk_departmentcode', 'mk_organization', 'mk_user_type', 'mk_nation', 'mk_province', 'mk_city', 'mk_district', 'mk_address', 'mk_deleted', 'bid']
    let _vars = ['tbid', 'errorcode', 'retmsg', 'billcode', 'bvoucher', 'fibvoucherdate', 'fiyear', 'username', 'fullname', 'modulardetailcode', 'roleid', 'mk_departmentcode', 'mk_organization', 'mk_user_type', 'mk_nation', 'mk_province', 'mk_city', 'mk_district', 'mk_address', 'mk_deleted', 'bid', 'mk_submit_type']
  
    // sql语句
    let _sql = ''
@@ -812,14 +1325,13 @@
    // 获取字段键值对
    formdata && formdata.forEach(form => {
      let _key = form.key.toLowerCase()
      datavars[_key] = form.value
  
      if (!_initvars.includes(_key)) {
        _initvars.push(_key)
        let val = form.value
  
        if (form.type === 'number' || form.type === 'rate') {
          if (isNaN(val)) {
          if (isNaN(val) || val === '') {
            val = 0
          }
          _initFormfields.push(`@${_key}=${val}`)
@@ -867,14 +1379,12 @@
  
    // 添加数据中字段,表单值优先(按钮不选行或多行拼接时跳过)
    if (data && btn.Ot !== 'notRequired' && columns && columns.length > 0) {
      datavars = {..._data, ...datavars}
      const setField = (col) => {
        if (!col.field) return
        let _key = col.field.toLowerCase()
  
        if (!_initvars.includes(_key)) {
          let _val = datavars.hasOwnProperty(_key) ? datavars[_key] : ''
          let _val = _data.hasOwnProperty(_key) ? _data[_key] : ''
  
          if (col.datatype && /^date/ig.test(col.datatype) && !_val) {
            _val = '1949-10-01'
@@ -929,7 +1439,7 @@
      _declarefields = ',' + _declarefields
    }
    _sql = `/* 系统生成 */
        Declare @tbid nvarchar(50),@ErrorCode nvarchar(50),@retmsg nvarchar(4000),@BillCode nvarchar(50),@BVoucher nvarchar(50),@FIBVoucherDate nvarchar(50), @FiYear nvarchar(50),@ModularDetailCode nvarchar(50), @UserName nvarchar(50),@FullName nvarchar(50),@RoleID nvarchar(512),@mk_departmentcode nvarchar(512),@mk_organization nvarchar(512),@mk_user_type nvarchar(20),@mk_nation nvarchar(50),@mk_province nvarchar(50),@mk_city nvarchar(50),@mk_district nvarchar(50),@mk_address nvarchar(100),@mk_deleted int,@bid nvarchar(50)${_declarefields}
        Declare @tbid nvarchar(50),@ErrorCode nvarchar(50),@retmsg nvarchar(4000),@BillCode nvarchar(50),@BVoucher nvarchar(50),@FIBVoucherDate nvarchar(50), @FiYear nvarchar(50),@ModularDetailCode nvarchar(50), @UserName nvarchar(50),@FullName nvarchar(50),@RoleID nvarchar(512),@mk_departmentcode nvarchar(512),@mk_organization nvarchar(512),@mk_user_type nvarchar(20),@mk_nation nvarchar(50),@mk_province nvarchar(50),@mk_city nvarchar(50),@mk_district nvarchar(50),@mk_address nvarchar(100),@mk_deleted int,@bid nvarchar(50),@mk_submit_type nvarchar(50)${_declarefields}
      `
  
    let userName = sessionStorage.getItem('User_Name') || ''
@@ -947,7 +1457,7 @@
    // 初始化凭证及用户信息字段
    _sql += `
        /* 凭证及用户信息初始化赋值 */
        select @BVoucher='',@FIBVoucherDate='',@FiYear='',@ErrorCode='',@retmsg='',@UserName='${userName}', @FullName='${fullName}', @RoleID='${RoleID}', @mk_departmentcode='${departmentcode}', @mk_organization='${organization}', @mk_user_type='${mk_user_type}', @mk_nation='${nation}', @mk_province='${province}', @mk_city='${city}', @mk_district='${district}', @mk_address='${address}', @mk_deleted=1, @bid='${BID}', @BillCode='', @ModularDetailCode=''
        select @BVoucher='',@FIBVoucherDate='',@FiYear='',@ErrorCode='',@retmsg='',@UserName='${userName}', @FullName='${fullName}', @RoleID='${RoleID}', @mk_departmentcode='${departmentcode}', @mk_organization='${organization}', @mk_user_type='${mk_user_type}', @mk_nation='${nation}', @mk_province='${province}', @mk_city='${city}', @mk_district='${district}', @mk_address='${address}', @mk_deleted=1, @bid='${BID}', @mk_submit_type='${submitType}', @BillCode='', @ModularDetailCode=''
        `
  
    // 表单变量赋值
@@ -971,21 +1481,49 @@
  /**
   * @description 按钮提交执行
   */
  execSubmit = (data, _resolve, formdata) => {
    const { setting, btn } = this.props
    this.moduleParams = null
  execSubmit = (data, _resolve, formdata, force) => {
    const { btn } = this.props
    if (
      (btn.intertype === 'system' || (btn.intertype === 'custom' && btn.procMode === 'system')) &&
      btn.sqlType !== 'insert' && btn.Ot !== 'notRequired' && btn.verify && btn.verify.invalid === 'true' &&
      setting.dataresource
    ) {
      MKEmitter.emit('queryModuleParam', btn.$menuId, (param) => {
        this.moduleParams = param
        this.execRealSubmit(data, _resolve, formdata)
      })
    if (btn.preButton && !force) {
      this.trigger(btn.preButton, data, _resolve, formdata, 0)
    } else {
      this.execRealSubmit(data, _resolve, formdata)
    }
  }
  trigger = (btnId, data, resolve, formdata, times) => {
    if (times > 50) {
      notification.warning({
        top: 92,
        message: window.GLOB.dict['pre_btn_failed'] || '前置按钮加载失败!',
        duration: 5
      })
      this.setState({loading: false})
      resolve()
      return
    }
    times++
    let node = document.getElementById('button' + btnId)
    if (node) {
      MKEmitter.emit('triggerBtnId', btnId, null, 'preButton', null, (res) => {
        if (!res) {
          this.setState({loading: false})
          resolve()
          return
        }
        if (res.status) {
          this.execSubmit(data, resolve, formdata, true)
        } else {
          this.execError(res)
        }
      })
    } else {
      setTimeout(() => {
        this.trigger(btnId, data, resolve, formdata, times)
      }, 100)
    }
  }
@@ -995,7 +1533,7 @@
    if (setting.supModule && !BID) {
      notification.warning({
        top: 92,
        message: '需要上级主键值!',
        message: setting.supModTip || window.GLOB.dict['sup_key_req'] || '需要上级主键值!',
        duration: 5
      })
      _resolve()
@@ -1005,8 +1543,22 @@
    if (btn.intertype === 'system' || btn.intertype === 'inner') { // 系统接口
      let params = []
      if (btn.intertype === 'system') {
      if (btn.intertype === 'system' && window.backend && window.GLOB.CacheData.has('sql_' + btn.uuid)) {
        params = this.getBackSystemParam(data, formdata)
      } else if (btn.intertype === 'system') {
        params = this.getSystemParam(data, formdata)
        if (btn.returnValue === 'true') {
          params = params.map(item => {
            item.script_type = 'Y'
            return item
          })
        }
        if (btn.database === 'sso' && window.GLOB.mainSystemApi) {
          params = params.map(item => {
            item.rduri = window.GLOB.mainSystemApi
            return item
          })
        }
      } else {
        params = this.getInnerParam(data, formdata)
      }
@@ -1041,7 +1593,7 @@
              }, 600)
            }
            this.triggerNote(res, _param.ID) // 消息
            this.triggerNote(res, _param) // 消息
            this.execSuccess(res)
          } else {
            this.execError(res)
@@ -1053,12 +1605,20 @@
          _resolve()
        })
      } else if (params.length <= 20 && btn.execType !== 'single') {
        if (window.backend && params[0].$backend && (!btn.verify || (btn.verify.printEnable !== 'true' && !btn.output))) {
          params = [{
            $backend: true,
            $type: 's_TableData_InUpDe',
            data: params.map(item => item.data[0])
          }]
        }
        let deffers = params.map((param, i) => {
          return new Promise(resolve => {
            setTimeout(() => {
              Api.genericInterface(param).then(res => {
                if (res.status) {
                  this.triggerNote(res, param.ID) // 消息
                  this.triggerNote(res, param) // 消息
                }
                resolve(res)
              }, (error) => {
@@ -1100,7 +1660,9 @@
      /** *********************调用外部接口************************* */
      let _params = [] // 请求参数数组
      if (btn.procMode === 'system') {
      if (btn.procMode === 'system' && window.backend && window.GLOB.CacheData.has('sql_' + btn.uuid)) {
        _params = this.getBackSystemParam(data, formdata)
      } else if (btn.procMode === 'system') {
        _params = this.getSystemParam(data, formdata, true)
        _params = _params.map(item => {
          item.script_type = 'Y'
@@ -1121,7 +1683,9 @@
    } else if (btn.intertype === 'custom') { // 系统接口
      let params = []
      if (btn.procMode === 'system') {
      if (btn.procMode === 'system' && window.backend && window.GLOB.CacheData.has('sql_' + btn.uuid)) {
        params = this.getBackSystemParam(data, formdata)
      } else if (btn.procMode === 'system') {
        params = this.getSystemParam(data, formdata, true)
        params = params.map(item => {
          item.script_type = 'Y'
@@ -1157,13 +1721,15 @@
      BID: param.BID || '',
      ID: param.ID || '',
      callbacksql: param.$callbacksql || '',
      mk_api_key: ''
      mk_api_key: '',
      backParam: param.$backParam || ''
    }
    if (!record.ID && btn.Ot !== 'notRequired' && param[setting.primaryKey]) {
      record.ID = param[setting.primaryKey]
    }
    delete param.$backParam
    delete param.$callbacksql
    if (param.$pice) {
@@ -1173,20 +1739,32 @@
      this.customOuterRequest(params, param, record, _resolve)
      return
    } else if (!param.func) {
    } else if (!param.func && !param.$backend) {
      this.customOuterRequest(params, param, record, _resolve)
      return
    }
    Api.genericInterface(param).then(res => {
    Api.genericInterface(param, btn.$innerScript, 'inner').then(res => {
      record.mk_api_key = res.mk_api_key || ''
      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)
        res.mk_ex_invoke = res.mk_ex_invoke + ''
        if (res.mk_ex_invoke === 'false') {
          if (params.length === 0) {
            this.execSuccess(res)
            _resolve()
          } else {
            this.customLoopRequest(params, _resolve)
          }
        } else if (res.mk_ex_invoke === 'true_inside') {
          let data = res.mk_in_api && typeof(res.mk_in_api) === 'object' ? res.mk_in_api : {}
          if (!data.hasOwnProperty('mk_api_key')) {
            data.mk_api_key = record.mk_api_key
          }
          this.customCallbackRequest(params, data, record, _resolve)
        } else {
          if (res.mk_ex_data) { // 数据分批执行
            if (Array.isArray(res.mk_ex_data) && res.mk_ex_data.length > 0) {
@@ -1227,7 +1805,7 @@
  // Api.directRequest('http://localhost:3001/test.xml', 'get', null, 'true').then(res => {
  //   let $x2js = new x2js()
  //   let jsonObj = $x2js.xml2js(res);
  //   console.info(jsonObj)
  //   window.mkInfo(jsonObj)
  // })
  /**
@@ -1243,6 +1821,7 @@
      url = btn.interface
    }
    url = url.replace(/@mydomain@/ig, window.GLOB.location)
    
    let param = {}
@@ -1264,12 +1843,36 @@
      })
    }
    if (/@.*@/.test(url)) {
      Object.keys(param).forEach(key => {
        let reg = new RegExp('@' + key + '@', 'ig')
        if (reg.test(url)) {
          url = url.replace(reg, param[key])
          delete param[key]
        }
      })
    }
    let _params = {
      url: url,
      method: btn.method || 'post'
    }
    if (btn.cross === 'true') {
    if (btn.ContentType) {
      _params.headers = {
        'Content-Type': btn.ContentType
      }
    }
    if (btn.$outerScript) {
      if (JSON.stringify(param) !== '{}') {
        if (btn.stringify === 'qs') {
          _params.data = qs.stringify(param)
        } else {
          _params.data = param
        }
      }
    } else if (btn.cross === 'true') {
      if (JSON.stringify(param) !== '{}') {
        if (btn.stringify === 'qs') {
          _params.data = qs.stringify(param)
@@ -1303,13 +1906,7 @@
      _params.method = 'post'
    }
    if (btn.ContentType) {
      _params.headers = {
        'Content-Type': btn.ContentType
      }
    }
    Api.directRequest(_params).then(res => {
    Api.directRequest(_params, btn.$outerScript, 'outer').then(res => {
      if (typeof(res) !== 'object') {
        let error = '未知的返回结果!'
@@ -1368,6 +1965,10 @@
        if (params.length === 0) {
          this.execSuccess(result)
          _resolve()
        } else if (btn.execInterval) {
          setTimeout(() => {
            this.customLoopRequest(params, _resolve)
          }, btn.execInterval)
        } else {
          this.customLoopRequest(params, _resolve)
        }
@@ -1376,6 +1977,8 @@
        _resolve()
      }
      return
    } else if (btn.callbackType === 'script' && record.backParam) {
      param = this.getCallBackendParam(result, record)
    } else if (btn.callbackType === 'script' || btn.callbackType === 'default') {
      param = this.getCallBackSql(result, record)
    } else if (btn.callbackType === 'func') {
@@ -1403,6 +2006,10 @@
        if (params.length === 0) {
          this.execSuccess(result)
          _resolve()
        } else if (btn.execInterval) {
          setTimeout(() => {
            this.customLoopRequest(params, _resolve)
          }, btn.execInterval)
        } else {
          this.customLoopRequest(params, _resolve)
        }
@@ -1418,13 +2025,17 @@
      param.menuname = param.menuname + '(回调)'
    }
    Api.genericInterface(param).then(res => {
    Api.genericInterface(param, btn.$callbackScript, 'callback').then(res => {
      if (res.status) {
        this.triggerNote(res, param.ID) // 消息
        this.triggerNote(res, param) // 消息
        if (params.length === 0) {
          this.execSuccess(res)
          _resolve()
        } else if (btn.execInterval) {
          setTimeout(() => {
            this.customLoopRequest(params, _resolve)
          }, btn.execInterval)
        } else {
          this.customLoopRequest(params, _resolve)
        }
@@ -1437,6 +2048,108 @@
      this.updateStatus()
      _resolve()
    })
  }
  getCallBackendParam = (result, record) => {
    const { btn } = this.props
    let lines = []
    let tables = []
    let param = fromJS(record.backParam).toJS()
    btn.verify.cbScripts.forEach(script => {
      if (script.status === 'false') return
      if (/\s#[a-z0-9_]+(\s|\()/ig.test(script.sql)) {
        tables.push(...script.sql.match(/\s#[a-z0-9_]+(\s|\()/ig))
      }
    })
    tables = tables.map(tb => tb.replace(/\s|\(/g, ''))
    if (result.$ErrCode) {
      delete result.$ErrCode
      delete result.$ErrMesg
    }
    let getDefaultSql = (obj, tb, bid, level) => {
      let vals = {}
      let subObjs = []
      let id = Utils.getuuid()
      delete obj.$$key
      Object.keys(obj).forEach(key => {
        let val = obj[key]
        if (val === null || val === undefined) return
        if (typeof(val) === 'object') {
          if (Array.isArray(val)) {
            val.forEach(item => {
              if (typeof(item) !== 'object' || Array.isArray(item)) return
              if (Object.keys(item).length === 0) return
              Object.keys(item).forEach(k => {
                if (item[k] === null) {
                  item[k] = ''
                }
              })
              item.$$key = tb + '_' + key
              subObjs.push(item)
            })
          } else if (Object.keys(val).length > 0) {
            val.$$key = tb + '_' + key
            subObjs.push(val)
          }
        } else {
          if (typeof(val) === 'string') {
            val = val.replace(/'/ig, '"')
          } else {
            val = val + ''
          }
          vals[key] = val
        }
      })
      vals.mk_level = level
      vals.mk_id = id
      vals.mk_bid = bid
      let isnew = true
      lines.forEach(line => {
        if (line.tb === tb) {
          line.values.push(vals)
          isnew = false
        }
      })
      if (isnew) {
        lines.push({
          tb: tb,
          type: tables.includes('#' + tb) ? '01' : '02',
          values: [vals]
        })
      }
      subObjs.forEach(item => {
        getDefaultSql(item, item.$$key, id, level + 1)
      })
    }
    getDefaultSql(result, btn.cbTable, '', 1)
    param.data[0].exps.push({
      key: 'mk_outer_params',  // 回调脚本的数据替换
      value: lines
    })
    let md5_id = ''
    if (window.GLOB.probation) {
      md5_id = md5('back_' + btn.uuid + JSON.stringify(param.data[0].exps) + Math.floor(new Date().getTime() / 600000))
      md5_id = moment().format('YYYYMMDDHHmmss') + md5_id.slice(-18)
    }
    param.data[0].md5_id = md5_id
    param.data[0].menuname = btn.logLabel + '(回调)'
    return param
  }
  getCallBackSql = (result, record) => {
@@ -1489,10 +2202,15 @@
          if (Array.isArray(val)) {
            val.forEach(item => {
              if (typeof(item) !== 'object' || Array.isArray(item)) return
              if (Object.keys(item).length > 0) {
                item.$$key = tb + '_' + key
                subObjs.push(item)
              }
              if (Object.keys(item).length === 0) return
              Object.keys(item).forEach(k => {
                if (item[k] === null) {
                  item[k] = ''
                }
              })
              item.$$key = tb + '_' + key
              subObjs.push(item)
            })
          } else if (Object.keys(val).length > 0) {
            val.$$key = tb + '_' + key
@@ -1508,11 +2226,12 @@
      })
      keys = keys.join(',')
      vals = vals.join(',')
      lines.push({
        table: md5(tb + keys),
        insert: `Insert into ${tbName} (${keys},[mk_level],[mk_id],[mk_bid])`,
        select: `Select ${vals.join(',')},'${level}','${id}','${bid}'`
        insert: `Insert into ${tbName} (${keys ? keys + ',' : ''}[mk_level],[mk_id],[mk_bid])`,
        select: `Select ${keys ? vals + ',' : ''}'${level}','${id}','${bid}'`
      })
      subObjs.forEach(item => {
@@ -1595,24 +2314,25 @@
      sql = sql.replace(/@SessionUid@/ig, `'${localStorage.getItem('SessionUid') || ''}'`)
      sql = sql.replace(/@UserID@/ig, `'${sessionStorage.getItem('UserID') || ''}'`)
      sql = sql.replace(/@Appkey@/ig, `'${window.GLOB.appkey || ''}'`)
      sql = sql.replace(/@lang@/ig, `'${sessionStorage.getItem('lang')}'`)
      sql = sql.replace(/@typename@/ig, `'admin'`)
      if (sessionStorage.getItem('dataM') === 'true') { // 数据权限
        sql = sql.replace(/\$@/ig, '/*').replace(/@\$/ig, '*/').replace(/@datam@/ig, '\'Y\'')
        sql = sql.replace(/\$@/ig, '/*').replace(/@\$/ig, '*/').replace(/@datam@/ig, `'Y'`)
      } else {
        sql = sql.replace(/@\$|\$@/ig, '').replace(/@datam@/ig, '\'\'')
        sql = sql.replace(/@\$|\$@/ig, '').replace(/@datam@/ig, `''`)
      }
      if (window.GLOB.debugger === true) {
        console.info('%c' + btn.logLabel + '(回调)', 'color: blue')
        console.info(sql.replace(/\n\s{8}/ig, '\n'))
        window.mkInfo('%c' + btn.logLabel + '(回调)', 'color: blue')
        window.mkInfo(sql.replace(/\n\s{8}/ig, '\n'))
      }
      param.LText = sql
      param.exec_type = 'y' // 后台解码
      param.exec_type = window.GLOB.execType || 'y' // 后台解码
      param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
      param.secretkey = Utils.encrypt('', param.timestamp)
      param.LText = Utils.formatOptions(param.LText)
      param.LText = Utils.formatOptions(param.LText, param.exec_type)
      param.menuname = btn.logLabel
      if (window.GLOB.probation) {
@@ -1639,7 +2359,7 @@
          `)}
        `))
        sql = sql.join('')
        console.info(sql.replace(/\n\s{10}/ig, '\n'))
        window.mkInfo(sql.replace(/\n\s{10}/ig, '\n'))
      }
    }
@@ -1658,11 +2378,15 @@
    Api.genericInterface(param).then(res => {
      if (res.status) {
        this.triggerNote(res, param.ID) // 消息
        this.triggerNote(res, param) // 消息
        if (params.length === 0) {
          this.execSuccess(res)
          _resolve()
        } else if (btn.execInterval) {
          setTimeout(() => {
            this.innerLoopRequest(params, btn, _resolve)
          }, btn.execInterval)
        } else {
          this.innerLoopRequest(params, btn, _resolve)
        }
@@ -1692,7 +2416,7 @@
    Api.genericInterface(param).then(res => {
      if (res.status) {
        this.triggerNote(res, param.ID) // 消息
        this.triggerNote(res, param) // 消息
        if (params.length === 0) {
          this.execSuccess(res)
@@ -1706,24 +2430,26 @@
          msg = msg.replace(/\n|\r/ig, '<br/>')
          msg = <span dangerouslySetInnerHTML={{__html: msg}}></span>
        }
        const _this = this
        const that = this
        confirm({
          title: '请确认',
          title: window.GLOB.dict['exec_sure'] || '请确认',
          content: msg,
          okText: window.GLOB.dict['ok'] || '确定',
          cancelText: window.GLOB.dict['cancel'] || '取消',
          onOk() {
            return new Promise(resolve => {
              Api.genericInterface(unCheckParam).then(result => {
                if (result.status) {
                  _this.triggerNote(result, param.ID) // 消息
                  that.triggerNote(result, param) // 消息
          
                  if (params.length === 0) {
                    _this.execSuccess(result)
                    that.execSuccess(result)
                    _resolve()
                  } else {
                    _this.checkLoopRequest(params, _resolve)
                    that.checkLoopRequest(params, _resolve)
                  }
                } else {
                  _this.execError(result)
                  that.execError(result)
                  _resolve()
                }
                resolve()
@@ -1731,7 +2457,7 @@
            })
          },
          onCancel() {
            _this.execError(res)
            that.execError(res)
            _resolve()
          }
        })
@@ -1750,7 +2476,7 @@
   * @description 外部请求循环执行
   */
  outerLoopRequest = (params, _resolve) => {
    const { setting, btn } = this.props
    const { setting, btn, BID } = this.props
    let param = params.shift()
@@ -1761,27 +2487,47 @@
    let record = {
      BID: param.BID || '',
      ID: param.ID || '',
      callbacksql: param.$callbacksql || ''
      callbacksql: param.$callbacksql || '',
      backParam: param.$backParam || ''
    }
    if (!record.ID && btn.Ot !== 'notRequired' && param[setting.primaryKey]) {
      record.ID = param[setting.primaryKey]
    }
    delete param.$backParam
    delete param.$callbacksql
    if (!param.func) {
    if (!param.func && !param.$backend) {
      this.outerOuterRequest(params, param, record, _resolve)
      return
    }
    Api.genericInterface(param).then(res => {
    Api.genericInterface(param, btn.$innerScript, 'inner').then(res => {
      if (res.status) {
        if ((res.mk_ex_invoke === 'false' || res.mk_ex_invoke === false) && params.length === 0) {
          this.execSuccess(res)
          _resolve()
        } else if ((res.mk_ex_invoke === 'false' || res.mk_ex_invoke === false) && params.length > 0) {
          this.outerLoopRequest(params, _resolve)
        res.mk_ex_invoke = res.mk_ex_invoke + ''
        if (res.mk_ex_invoke === 'false') {
          if (params.length === 0) {
            this.execSuccess(res)
            _resolve()
          } else {
            this.outerLoopRequest(params, _resolve)
          }
        } else if (res.mk_ex_invoke === 'true_inside') {
          let data = res.mk_in_api && typeof(res.mk_in_api) === 'object' ? res.mk_in_api : {}
          if (!data.hasOwnProperty('mk_api_key')) {
            data.mk_api_key = res.mk_api_key || ''
          }
          // 使用处理后的数据调用外部接口
          let keys = Object.keys(data) // 提交外部接口前,添加BID
          if (BID && keys.filter(key => key.toLowerCase() === 'bid').length === 0) {
            data.BID = BID
          }
          this.outerCallbackRequest(params, data, record, {}, _resolve)
        } else {
          delete res.mk_ex_invoke
          delete res.ErrCode
@@ -1791,8 +2537,8 @@
          // 使用处理后的数据调用外部接口
          let keys = Object.keys(res) // 提交外部接口前,添加BID
          if (this.props.BID && keys.filter(key => key.toLowerCase() === 'bid').length === 0) {
            res.BID = this.props.BID
          if (BID && keys.filter(key => key.toLowerCase() === 'bid').length === 0) {
            res.BID = BID
          }
          if (res.mk_api_key) {
@@ -1873,7 +2619,7 @@
      }
    }
    Api.genericInterface(result).then(res => {
    Api.genericInterface(result, btn.$outerScript, 'outer').then(res => {
      if (!res) return // LoginError时中断请求
      if (ver_token && res.ErrCode === 'token_error') {
        res.ErrCode = 'E'
@@ -1908,6 +2654,10 @@
        if (params.length === 0) {
          this.execSuccess(result)
          _resolve()
        } else if (btn.execInterval) {
          setTimeout(() => {
            this.outerLoopRequest(params, _resolve)
          }, btn.execInterval)
        } else {
          this.outerLoopRequest(params, _resolve)
        }
@@ -1924,6 +2674,8 @@
        _resolve()
      }
      return
    } else if (btn.callbackType === 'script' && record.backParam) {
      param = this.getCallBackendParam(result, record)
    } else if (btn.callbackType === 'script' || btn.callbackType === 'default') {
      param = this.getCallBackSql(result, record)
    } else if (btn.callbackType === 'func' || btn.callbackFunc) {
@@ -1936,17 +2688,24 @@
        func: btn.callbackFunc
      }
      // special 函数 s_sDataDictb_TBBack 云端验证
      if (window.GLOB.mkHS && param.func === 's_sDataDictb_TBBack' && param.LTextOut) {
        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 (window.GLOB.mkHS) {
        if (btn.callbackFunc === 's_sVersion_Local_add' && window.GLOB.forcedUpdate) { // special 传输号添加回调处理
          param.local_userid = sessionStorage.getItem('LocalUserID') || ''
        } else if (btn.callbackFunc === 's_sDataDictb_TBBack' && param.LTextOut) { // special 函数 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)
        }
      }
    } else {
      if (result.status) {
        if (params.length === 0) {
          this.execSuccess(result)
          _resolve()
        } else if (btn.execInterval) {
          setTimeout(() => {
            this.outerLoopRequest(params, _resolve)
          }, btn.execInterval)
        } else {
          this.outerLoopRequest(params, _resolve)
        }
@@ -1962,14 +2721,18 @@
      param.menuname = param.menuname + '(回调)'
    }
    Api.genericInterface(param).then(res => {
    Api.genericInterface(param, btn.$callbackScript, 'callback').then(res => {
      if (res.status) {
        this.triggerNote(res, param.ID) // 消息
        this.triggerNote(res, param) // 消息
        // 一次请求成功,进行下一项请求
        if (params.length === 0) {
          this.execSuccess(res)
          _resolve()
        } else if (btn.execInterval) {
          setTimeout(() => {
            this.outerLoopRequest(params, _resolve)
          }, btn.execInterval)
        } else {
          this.outerLoopRequest(params, _resolve)
        }
@@ -1986,30 +2749,77 @@
    delete result.message
    delete result.status
    result.func = btn.callbackFunc
    let ssoParam = null
    let sinParam = null
    let callParam = {...outParam, ...result}
    if (callParam.LTextOut) {
      callParam.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
      callParam.secretkey = Utils.encrypt(callParam.LTextOut, callParam.timestamp)
      callParam.open_key = Utils.encryptOpenKey(callParam.secretkey, callParam.timestamp)
    }
    callParam.func = btn.callbackFunc
    callParam.userid = sessionStorage.getItem('LocalUserID') || ''
    callParam.LoginUID = sessionStorage.getItem('LocalLoginUID') || ''
    if (callParam.UpType === 'SSO' && window.GLOB.localSystemApi) {
    if (result.LTextOut) {
      callParam.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
      callParam.secretkey = Utils.encrypt(callParam.LTextOut, callParam.timestamp)
      callParam.open_key = Utils.encryptOpenKey(callParam.secretkey, callParam.timestamp)
    } else {
      callParam = {...outParam}
      callParam.func = btn.callbackFunc
      callParam.MenuNO = 'sVersionDetail_LocalM'
      callParam.UpType = 'SSO'
      callParam.LTextOut = 'minke'
      callParam.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
      callParam.secretkey = Utils.encrypt(callParam.LTextOut, callParam.timestamp)
      callParam.open_key = Utils.encryptOpenKey(callParam.secretkey, callParam.timestamp)
      callParam.userid = sessionStorage.getItem('LocalUserID') || ''
      callParam.LoginUID = sessionStorage.getItem('LocalLoginUID') || ''
      delete result.ErrCode
      delete result.ErrMesg
      sinParam = {...result}
      sinParam.func = 'sPC_TrdMenu_AddUpt_sso'
      if (window.GLOB.sysType === 'local') {
        if (!window.GLOB.systemType && window.GLOB.cloudServiceApi) {
          sinParam.rduri = window.GLOB.cloudServiceApi
        } else if (window.GLOB.localSystemApi) {
          sinParam.rduri = window.GLOB.localSystemApi
          sinParam.userid = sessionStorage.getItem('LocalUserID') || ''
          sinParam.LoginUID = sessionStorage.getItem('LocalLoginUID') || ''
        }
      }
    }
    if (result.UpType === 'SSO' && window.GLOB.localSystemApi) {
      ssoParam = fromJS(callParam).toJS()
      ssoParam.rduri = window.GLOB.localSystemApi
      delete ssoParam.UpType
    } else {
      delete callParam.UpType
    }
    if (ssoParam) {
    if (sinParam) {
      Api.genericInterface(sinParam).then(res => {
        if (!res.status) {
          this.execError(res)
          _resolve()
        } else {
          Api.genericInterface(callParam).then(re => {
            if (!re.status) {
              this.execError(re)
              _resolve()
            } else {
              if (params.length === 0) {
                this.clearBackCache()
                this.execSuccess(res)
                _resolve()
              } else {
                this.outerLoopRequest(params, _resolve)
              }
            }
          })
        }
      })
    } else if (ssoParam) {
      Api.genericInterface(ssoParam).then(res => {
        if (!res.status) {
          this.execError(res)
@@ -2021,6 +2831,7 @@
              _resolve()
            } else {
              if (params.length === 0) {
                this.clearBackCache()
                this.execSuccess(res)
                _resolve()
              } else {
@@ -2037,6 +2848,7 @@
          _resolve()
        } else {
          if (params.length === 0) {
            this.clearBackCache()
            this.execSuccess(re)
            _resolve()
          } else {
@@ -2045,6 +2857,34 @@
        }
      })
    }
  }
  clearBackCache = () => {
    if (!window.GLOB.backend) return
    Api.cacheInterface({}).then(res => {
      if (!res.status) {
        notification.warning({
          top: 92,
          message: res.message || '缓存清空失败!',
          duration: 5
        })
      } else if (window.GLOB.localSystemApi) {
        Api.cacheInterface({
          userid: sessionStorage.getItem('LocalUserID') || sessionStorage.getItem('UserID') || '',
          LoginUID: sessionStorage.getItem('LocalLoginUID') || sessionStorage.getItem('LoginUID') || '',
          rduri: window.GLOB.localSystemApi.replace('dostars', 'excache')
        }).then(result => {
          if (!result.status) {
            notification.warning({
              top: 92,
              message: result.message || '缓存清空失败!',
              duration: 5
            })
          }
        })
      }
    })
  }
  /**
@@ -2057,9 +2897,32 @@
   */
  execSuccess = (res = {}) => {
    const { btn } = this.props
    const { autoMatic } = this.state
    const { autoMatic, dict } = this.state
    if (autoMatic) {
    if (btn.resetForms) {
      let data = {}
      Object.keys(res).forEach(key => {
        data[key.toLowerCase()] = res[key]
      })
      delete data.errcode
      delete data.errmesg
      delete data.message
      delete data.status
      MKEmitter.emit('resetForms', btn.uuid, data)
      MKEmitter.emit('refreshByButtonResult', btn.$menuId, 'resetData', btn, null, null, data)
    }
    if (this.preCallback) {
      this.setState({
        loading: false,
        visible: false
      })
      this.preCallback(res)
      return
    } else if (autoMatic) {
      this.setState({
        loading: false,
        visible: false
@@ -2069,13 +2932,24 @@
    }
    let sign = ''
    let focusField = ''
    if (/@focus:[a-z0-9_]+@/i.test(res.message)) {
      let val = res.message.match(/@focus:[a-z0-9_]+@/i)
      res.message = res.message.replace(/@focus:[a-z0-9_]+@/i, '')
      focusField = val ? val[0].replace(/@focus:|@/ig, '') : ''
      if (!res.message) {
        res.ErrCode = '-1'
      }
    }
    if (/^@speak@/i.test(res.message)) {
      res.message = res.message.replace(/^@speak@/i, '')
      let val = res.message.match(/<<.*>>/)
      res.message = res.message.replace(/\s*<<.*>>\s*/g, '')
      val = val ? val[0].replace(/<<|>>/g, '') : ''
      if (/^http/.test(val)) {
      if (/^(http|\/\/)/.test(val)) {
        let audio = document.createElement('audio')
        audio.src = val
        audio.play()
@@ -2084,9 +2958,10 @@
      if (!res.message) {
        res.ErrCode = '-1'
      }
    } else if (/@close_tab@|@close_popup@|@goback@|@no_target_menu@/i.test(res.message)) {
      sign = res.message.match(/@close_tab@|@close_popup@|@goback@|@no_target_menu@/i)[0].toLowerCase()
      res.message = res.message.replace(/@close_tab@|@close_popup@|@goback@|@no_target_menu@/i, '')
    }
    if (/@close_tab@|@close_popup@|@goback@|@no_target_menu@|@open_target_menu@/i.test(res.message)) {
      sign = res.message.match(/@close_tab@|@close_popup@|@goback@|@no_target_menu@|@open_target_menu@/i)[0].toLowerCase()
      res.message = res.message.replace(/@close_tab@|@close_popup@|@goback@|@no_target_menu@|@open_target_menu@/i, '')
    }
    let id = ''
@@ -2104,20 +2979,21 @@
      if (btn.formType !== 'counter' || res.message) {
        notification.success({
          top: 92,
          message: res.message || '执行成功!',
          message: res.message || dict['exc_success'] || '执行成功!',
          duration: btn.verify && btn.verify.stime ? btn.verify.stime : 2
        })
      }
    } else if (res.ErrCode === 'Y') { // 执行成功
      let msg = res.message || '执行成功!'
      let msg = res.message || dict['exc_success'] || '执行成功!'
      if (/\n|\r/.test(msg)) {
        msg = msg.replace(/\n|\r/ig, '<br/>')
        msg = <span dangerouslySetInnerHTML={{__html: msg}}></span>
      }
      Modal.success({
        title: msg,
        okText: dict['got_it'] || '知道了',
        onOk: () => {
          this.successContinue(sign, id)
          this.successContinue(sign, id, res, focusField)
        }
      })
      return
@@ -2125,12 +3001,16 @@
    }
    this.successContinue(sign, id)
    this.successContinue(sign, id, res, focusField)
  }
  successContinue = (sign, id) => {
  successContinue = (sign, id, res, focusField) => {
    const { btn } = this.props
    const { btnconfig } = this.state
    if (focusField) {
      MKEmitter.emit('resetFocus', btn.uuid, focusField)
    }
    this.setState({
      loadingNumber: '',
@@ -2145,12 +3025,37 @@
    }
    let tabId = ''
    let menu = null
    if (btn.refreshTab && btn.refreshTab.length > 0) {
      tabId = btn.refreshTab[btn.refreshTab.length - 1]
    }
    if (window.backend && btn.outerFunc && ['bd_workers_create_user_sso', 's_susers_del', 's_susers_add', 's_susers_update', 's_susers_start', 's_susers_admin'].includes(btn.outerFunc.toLowerCase())) {
      setTimeout(() => {
        this.clearBackSqlCache()
      }, 300)
    }
    if (btn.openmenu && Array.isArray(btn.openmenu) && btn.openmenu.length > 0 && sign !== '@no_target_menu@') {
      let menuId = btn.openmenu.slice(-1)[0]
      if (window.GLOB.mkThdMenus.has(menuId)) {
        menu = {...window.GLOB.mkThdMenus.get(menuId), param: { $BID: id }}
      } else if (btn.MenuID) {
        menu = {
          MenuID: btn.MenuID,
          MenuName: btn.MenuName,
          type: btn.tabType,
          param: { $BID: id }
        }
      }
    }
    if (tabId && btn.$MenuID === tabId) { // 刷新当前菜单时,停止其他操作
      MKEmitter.emit('reloadMenuView', tabId, 'table')
      MKEmitter.emit('reloadMenuView', tabId, btn.urlPar === 'true')
      if (menu) {
        MKEmitter.emit('modifyTabs', menu, true)
      }
      return
    }
@@ -2168,18 +3073,46 @@
    
    if (btn.syncComponentId) {
      if (btn.syncComponentId === 'multiComponent') {
        btn.syncComponentIds.forEach((id, i) => {
          setTimeout(() => {
            MKEmitter.emit('reloadData', id)
          }, 20 * i)
        })
        if (btn.syncDelay) {
          this.delayTimer && clearTimeout(this.delayTimer)
          this.delayTimer = setTimeout(() => {
            btn.syncComponentIds.forEach((id, i) => {
              setTimeout(() => {
                if (/\$focus/.test(id)) {
                  MKEmitter.emit('reloadData', id.split('$')[0], id.split('$')[1])
                } else {
                  MKEmitter.emit('reloadData', id)
                }
              }, 20 * i)
            })
          }, btn.syncDelay)
        } else {
          btn.syncComponentIds.forEach((id, i) => {
            setTimeout(() => {
              if (/\$focus/.test(id)) {
                MKEmitter.emit('reloadData', id.split('$')[0], id.split('$')[1])
              } else {
                MKEmitter.emit('reloadData', id)
              }
            }, 20 * i)
          })
        }
      } else if (/\$focus/.test(btn.syncComponentId)) {
        MKEmitter.emit('reloadData', btn.syncComponentId.split('$')[0], btn.syncComponentId.split('$')[1])
      } else {
        MKEmitter.emit('reloadData', btn.syncComponentId)
        if (btn.syncDelay) {
          this.delayTimer && clearTimeout(this.delayTimer)
          this.delayTimer = setTimeout(() => {
            MKEmitter.emit('reloadData', btn.syncComponentId)
          }, btn.syncDelay)
        } else {
          MKEmitter.emit('reloadData', btn.syncComponentId)
        }
      }
    }
    if (tabId) {
      MKEmitter.emit('reloadMenuView', tabId, 'table')
      MKEmitter.emit('reloadMenuView', tabId, btn.urlPar === 'true')
    }
    
    if (btn.switchTab && btn.switchTab.length > 0) {
@@ -2193,36 +3126,60 @@
      node && node.scrollIntoView({behavior: 'smooth', block: 'center', inline: 'nearest'})
    }
    if (btn.openmenu && Array.isArray(btn.openmenu) && btn.openmenu.length > 0 && sign !== '@no_target_menu@') {
      let menuId = btn.openmenu.slice(-1)[0]
      let menu = null
      if (window.GLOB.mkThdMenus.has(menuId)) {
        menu = {...window.GLOB.mkThdMenus.get(menuId), param: { $BID: id }}
      } else if (btn.MenuID) {
        menu = {
          MenuID: btn.MenuID,
          MenuName: btn.MenuName,
          type: btn.tabType,
          param: { $BID: id }
        }
      }
      if (menu) {
        MKEmitter.emit('modifyTabs', menu, true)
      }
    if (menu) {
      MKEmitter.emit('modifyTabs', menu, true)
    }
    if (btn.execSuccess === 'popclose' && btn.$tabId) { // 标签关闭刷新
      MKEmitter.emit('refreshPopButton', btn.$tabId)
    }
    if (btn.verify && btn.verify.linkEnable === 'true') {
      let url = ''
      if (window.GLOB.systemType === 'production') {
        url = btn.verify.linkProUrl
        if (!url) {
          notification.warning({
            top: 92,
            message: window.GLOB.dict['no_prod_link'] || '尚未设置正式系统链接地址!',
            duration: 5
          })
          return
        }
      } else {
        url = btn.verify.linkUrl
      }
      if (/@/.test(url)) {
        Object.keys(res).forEach(key => {
          url = url.replace(new RegExp('@' + key + '@', 'ig'), res[key])
        })
      }
      if (!/^http/.test(url)) {
        url = window.location.origin + url
      }
      window.open(url)
    }
  }
  triggerNote = (res, ID) => {
  clearBackSqlCache = () => {
    Api.cacheInterface({}).then(res => {
      if (!res.status) {
        notification.warning({
          top: 92,
          message: res.message || '缓存清空失败!',
          duration: 5
        })
      }
    })
  }
  triggerNote = (res, param) => {
    const { btn } = this.props
    if (!btn.verify) return
    if (btn.verify.noteEnable !== 'true' && btn.verify.wxNote !== 'true' && btn.verify.printEnable !== 'true') return
    if (btn.verify.noteEnable !== 'true' && btn.verify.wxNote !== 'true' && btn.verify.printEnable !== 'true' && btn.verify.emailEnable !== 'true' && btn.verify.DeepSeekable !== 'true') return
    let id = ''
    if (btn.output) {
@@ -2230,13 +3187,28 @@
    }
    if (btn.verify.printEnable === 'true') {
      this.billPrint(id || ID)
      let _id = id || param.ID
      if (!_id && param.data && param.data[0] && param.data[0].exps) {
        param.data[0].exps.forEach(cell => {
          if (cell.key === 'ID') {
            _id = cell.value
          }
        })
      }
      this.billPrint(_id)
    }
    if (!id) return
    if (btn.verify.noteEnable === 'true') {
      this.sendMessage(btn.verify, id)
    }
    if (btn.verify.emailEnable === 'true') {
      this.sendEmail(btn.verify, id)
    }
    if (btn.verify.DeepSeekable === 'true') {
      this.openDeepSeek(id)
    }
    if (btn.verify.wxNote === 'true') {
      if (btn.verify.wxTemplateId === 'mk_category_temp') {
@@ -2259,16 +3231,65 @@
    if (!id) return
    setTimeout(() => {
      window.open('#/billprint/' + window.btoa(window.encodeURIComponent(JSON.stringify({ id: id, tempId: btn.verify.printTempId, pageId: btn.$MenuID || '', dataM: sessionStorage.getItem('dataM') }))))
    }, 500)
    if (btn.verify.preHandle === 'true' && btn.verify.pre_func && /#position-print/.test(btn.verify.pre_func)) {
      MKEmitter.emit('queryModuleParam', btn.$menuId, (res) => {
        let searches = {}
        res.search && res.search.forEach(item => {
          searches[item.key] = item.value
        })
        let _param = { id: id || '', tempId: btn.verify.printTempId, pageId: btn.$MenuID || '', dataM: sessionStorage.getItem('dataM')}
        try {
          // eslint-disable-next-line
          let func = new Function('btn', 'searches', 'param', 'systemType', btn.verify.pre_func)
          _param = func(btn, searches, _param, window.GLOB.systemType)
        } catch (e) {
          console.warn(e)
        }
        if (!_param || _param.error) {
          notification.warning({
            top: 92,
            message: _param ? _param.error : '未获取到打印参数,自定义脚本错误!',
            duration: 5
          })
          return
        }
        window.open('#/billprint/' + window.btoa(window.encodeURIComponent(JSON.stringify(_param))))
      })
    } else {
      setTimeout(() => {
        window.open('#/billprint/' + window.btoa(window.encodeURIComponent(JSON.stringify({ id: id, tempId: btn.verify.printTempId, pageId: btn.$MenuID || '', dataM: sessionStorage.getItem('dataM') }))))
      }, 200)
    }
  }
  sendWxMessage = (verify, id) => {
    if (!window.GLOB.nginx) {
    let domain = window.GLOB.baseurl
    let appId = window.GLOB.WXAppID || ''
    if (verify.wxAppId && verify.wxAppId !== appId) {
      appId = verify.wxAppId
      if (!window.GLOB.WXApps || window.GLOB.WXApps.findIndex(item => item.appId === verify.wxAppId) === -1) {
        notification.warning({
          top: 92,
          message: '按钮关联公众号不在可用列表中,请重新保存按钮配置!',
          duration: 5
        })
        return
      }
    }
    if (['8IFltwzyKcu15iA8fqSyb6m-pMa88a3ZTu0No3vDHgo', 'LOB-bbt9jVncGh7IOAUdESh1Sgzcbt62UwOqSqcK9ok'].includes(verify.wxTemplateId) && window.GLOB.sysType !== 'cloud') {
      domain = 'https://cloud.mk9h.cn/'
      appId = 'wx4d8a34c8d4494872'
    }
    if (!appId) {
      notification.warning({
        top: 92,
        message: 'nginx服务尚未开启,不可发送模板消息。',
        message: '尚未添加公众号ID,不可发送模板消息。',
        duration: 5
      })
      return
@@ -2279,16 +3300,9 @@
      upid: id
    }
    param.LText = Utils.formatOptions(Utils.getuuid())
    param.LText = Utils.getuuid()
    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) && window.GLOB.sysType !== 'cloud') {
      domain1 = 'https://cloud.mk9h.cn/'
      domain2 = 'https://cloud.mk9h.cn:8443/'
    }
    Api.genericInterface(param).then(res => {
      // res.send_data = [{openid: 'o2E7gvoSFvQRG7I8_gZxf4y3ONkQ', send_id: Utils.getuuid(), p1: '010000000001', p2: '明科', p3: 'dddd', p4: '顺风', p5: '成功'}]
@@ -2316,9 +3330,9 @@
      if (verify.wxNoteLink === 'url' && verify.wxNoteLinkUrl) {
        _param.url = verify.wxNoteLinkUrl
      } else if (verify.wxNoteLink === 'miniProgram' && window.GLOB.WXminiAppID) {
      } else if (verify.wxNoteLink === 'miniProgram' && (window.GLOB.WXminiAppID || verify.wxNoteMiniId)) {
        _param.miniprogram = {
          appid: window.GLOB.WXminiAppID,
          appid: verify.wxNoteMiniId || window.GLOB.WXminiAppID,
          pagepath: '/pages/index/index'
        }
@@ -2352,62 +3366,63 @@
        return m
      })
      Api.wxAccessToken(domain1).then(res => {
        if (!res.oa_access_token) return
        params.forEach(n => {
          Api.wxNginxRequest(`${domain2}cgi-bin/message/template/send?access_token=${res.oa_access_token}`, 'post', JSON.stringify(n)).then(re => {
            if (verify.wxNoteCallback === 'true') {
              let msg = re.errmsg || ''
      // cgi-bin/message/template/send
      params.forEach(n => {
        Api.directRequest({
          url: domain + 'wechat/send?appid=' + appId,
          method: 'post',
          data: JSON.stringify(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: msg
              }
              _p.LText = Utils.formatOptions(Utils.getuuid())
              _p.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
              _p.secretkey = Utils.encrypt(_p.LText, _p.timestamp)
              Api.genericInterface(_p).then(result => {
                if (!result.status) {
                  notification.warning({
                    top: 92,
                    message: result.message,
                    duration: 5
                  })
                }
              })
            } else if (re.errcode !== 0 && re.errmsg) {
              let msgs = [
                {errcode: -1, errmsg: '系统繁忙,请稍候再试'},
                {errcode: 40001, errmsg: 'access_token 无效'},
                {errcode: 40003, errmsg: '不合法的 OpenID'},
                {errcode: 40014, errmsg: '不合法的 access_token'},
                {errcode: 40033, errmsg: '不合法的请求字符'},
                {errcode: 43004, errmsg: '需要接收者关注'},
                {errcode: 43019, errmsg: '需要将接收者从黑名单中移除'},
                {errcode: 50005, errmsg: '用户未关注公众号'}
              ]
              let msg = msgs.filter(m => m.errcode === re.errcode)[0]
              msg = msg || re
              notification.warning({
                top: 92,
                message: msg.errmsg,
                duration: 5
              })
            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: msg
            }
            _p.LText = Utils.getuuid()
            _p.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
            _p.secretkey = Utils.encrypt(_p.LText, _p.timestamp)
            Api.genericInterface(_p).then(result => {
              if (!result.status) {
                notification.warning({
                  top: 92,
                  message: result.message,
                  duration: 5
                })
              }
            })
          } else if (re.errcode !== 0 && re.errmsg) {
            let msgs = [
              {errcode: -1, errmsg: '系统繁忙,请稍候再试'},
              {errcode: 40001, errmsg: 'access_token 无效'},
              {errcode: 40003, errmsg: '不合法的 OpenID'},
              {errcode: 40014, errmsg: '不合法的 access_token'},
              {errcode: 40033, errmsg: '不合法的请求字符'},
              {errcode: 43004, errmsg: '需要接收者关注'},
              {errcode: 43019, errmsg: '需要将接收者从黑名单中移除'},
              {errcode: 50005, errmsg: '用户未关注公众号'}
            ]
            let msg = msgs.filter(m => m.errcode === re.errcode)[0]
            msg = msg || re
            notification.warning({
              top: 92,
              message: msg.errmsg,
              duration: 5
            })
          }
        })
      })
    })
@@ -2416,12 +3431,12 @@
  sendMessage = (verify, id) => {
    let param = {
      func: 's_get_sms_local',
      TypeCharOne: verify.noteTemp, // N不同内容,Y相同内容
      TypeCharTwo: verify.noteType, // N定时,Y实时
      TypeCharOne: verify.noteTemp || 'Y', // N不同内容,Y相同内容
      TypeCharTwo: verify.noteType || 'N', // N定时,Y实时
      upid: id
    }
    param.LText = Utils.formatOptions(Utils.getuuid())
    param.LText = Utils.getuuid()
    param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
    param.secretkey = Utils.encrypt(param.LText, param.timestamp)
@@ -2436,9 +3451,9 @@
      }
      let _param = {
        templatecode: verify.noteCode, // 模板编码
        TypeCharOne: verify.noteTemp,  // N不同内容,Y相同内容
        ID: verify.noteId || ''        // 模板Id,暂时未使用
        templatecode: verify.noteCode,        // 模板编码
        TypeCharOne: verify.noteTemp || 'Y',  // N不同内容,Y相同内容
        ID: verify.noteId || ''               // 模板Id,暂时未使用
      }
      _param.submitdate = res.submitdate
@@ -2446,17 +3461,17 @@
      let limit = 5 // 实时最大为5条,定时最大为100条
      let mobMap = new Map()
      if (verify.noteType === 'N') {
      if (verify.noteType === 'Y') {
        _param.func = 's_get_sms_sso_realtime'
      } else {
        _param.func = 's_get_sms_sso_timer'
        limit = 100
      } else if (verify.noteType === 'Y') {
        _param.func = 's_get_sms_sso_realtime'
      }
      let Ltext = []
      let error = false
      if (verify.noteTemp === 'Y') {
      if (verify.noteTemp !== 'N') {
        _param.p1 = res.p1 || ''
        _param.p2 = res.p2 || ''
        _param.p3 = res.p3 || ''
@@ -2465,19 +3480,19 @@
        let _p = _param.p1 + _param.p2 + _param.p3 + _param.p4 + _param.p5
        if (/\/|\.|.*共.*产|.*习.*近|面试|邀请|下载|红包|招聘|好评|评价|政务通知|缴费|保险|股票|金融|房地产|教育|游戏|微信|Q/.test(_p)) {
        if (/\/|.*共.*产|.*习.*近|面试|邀请|下载|红包|招聘|好评|评价|政务通知|缴费|保险|股票|金融|房地产|教育|游戏|微信/.test(_p)) {
          error = true
        }
      }
      res.send_data && res.send_data.forEach(item => {
        if (item.mob && !mobMap.has(item.mob) && Ltext.length < limit) {
          if (verify.noteTemp === 'Y') {
          if (verify.noteTemp !== 'N') {
            Ltext.push(`'${item.mob}'`)
          } else {
            let _p = `'${item.p1 || ''}','${item.p2 || ''}','${item.p3 || ''}','${item.p4 || ''}','${item.p5 || ''}','${item.mob}'`
            if (/\/|\.|.*共.*产|.*习.*近|面试|邀请|下载|红包|招聘|好评|评价|政务通知|缴费|保险|股票|金融|房地产|教育|游戏|微信|Q/.test(_p)) {
            if (/\/|.*共.*产|.*习.*近|面试|邀请|下载|红包|招聘|好评|评价|政务通知|缴费|保险|股票|金融|房地产|教育|游戏|微信/.test(_p)) {
              error = true
            }
@@ -2544,6 +3559,169 @@
    })
  }
  sendEmail = (verify, id) => {
    let param = {
      func: 's_get_email_local',
      TypeCharOne: verify.emailTemp || 'Y', // N不同内容,Y相同内容
      TypeCharTwo: verify.emailType || 'N', // N定时,Y实时
      upid: id
    }
    param.LText = Utils.getuuid()
    param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
    param.secretkey = Utils.encrypt(param.LText, param.timestamp)
    Api.genericInterface(param).then(res => {
      if (!res.status) {
        notification.warning({
          top: 92,
          message: res.message,
          duration: 5
        })
        return
      }
      let _param = {
        msn_email_temp_no: verify.emailCode,   // 模板编码
        TypeCharOne: verify.emailTemp || 'Y',  // N不同内容,Y相同内容
        ID: verify.emailId || ''               // 模板Id,暂时未使用
      }
      _param.submitdate = res.submitdate
      let limit = 5 // 实时最大为5条,定时最大为100条
      let mobMap = new Map()
      if (verify.emailType === 'Y') {
        _param.func = 's_get_email_sso_realtime'
      } else {
        _param.func = 's_get_email_sso_timer'
        limit = 100
      }
      let Ltext = []
      let error = false
      if (verify.emailTemp !== 'N') {
        _param.p1 = res.p1 || ''
        _param.p2 = res.p2 || ''
        _param.p3 = res.p3 || ''
        _param.p4 = res.p4 || ''
        _param.p5 = res.p5 || ''
        let _p = _param.p1 + _param.p2 + _param.p3 + _param.p4 + _param.p5
        if (/\/|.*共.*产|.*习.*近|面试|邀请|下载|红包|招聘|好评|评价|政务通知|缴费|保险|股票|金融|房地产|教育|游戏|微信/.test(_p)) {
          error = true
        }
      }
      res.send_data && res.send_data.forEach(item => {
        if (item.email && !mobMap.has(item.email) && Ltext.length < limit) {
          if (verify.emailTemp !== 'N') {
            Ltext.push(`'${item.email}'`)
          } else {
            let _p = `'${item.p1 || ''}','${item.p2 || ''}','${item.p3 || ''}','${item.p4 || ''}','${item.p5 || ''}','${item.email}'`
            if (/\/|.*共.*产|.*习.*近|面试|邀请|下载|红包|招聘|好评|评价|政务通知|缴费|保险|股票|金融|房地产|教育|游戏|微信/.test(_p)) {
              error = true
            }
            Ltext.push(_p)
          }
          mobMap.set(item.email, true)
        }
      })
      if (error) {
        notification.warning({
          top: 92,
          message: '消息中含有非法字符',
          duration: 5
        })
        return
      }
      if (Ltext.length === 0) return
      Ltext = Ltext.join(';')
      _param.LText = window.btoa(window.encodeURIComponent(Ltext))
      _param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
      _param.secretkey = Utils.encrypt(_param.LText, _param.timestamp)
      _param.rduri = 'https://sso.mk9h.cn/webapi/dostars'
      _param.userid = 'bh0bapabtd45epsgra79segbch6c1ibk'
      _param.LoginUID = 'bh0bapabtd45epsgra79segbch6c1ibk'
      Api.genericInterface(_param).then(result => {
        if (!result.status) {
          notification.warning({
            top: 92,
            message: result.message,
            duration: 5
          })
        }
      }, (error) => {
        if (error && error.ErrCode === 'LoginError') {
          let param = {
            func: 's_visitor_login',
            timestamp: moment().format('YYYY-MM-DD HH:mm:ss'),
            SessionUid: 'bh0bapabtd45epsgra79segbch6c1ibk',
            TypeCharOne: 'pc',
            appkey: '202004041613277377A6A2456D34A4948AE84'
          }
          param.LText = md5(window.btoa('bh0bapabtd45epsgra79segbch6c1ibk' + param.timestamp))
          param.secretkey = md5(param.LText + 'mingke' + param.timestamp)
          let params = {
            url: 'https://sso.mk9h.cn/webapi/dologon',
            method: 'post',
            data: JSON.stringify(param)
          }
          Api.directRequest(params)
          return
        }
      })
    })
  }
  openDeepSeek = (id) => {
    let param = {
      func: 's_get_deepseek_local',
      upid: id
    }
    param.LText = Utils.getuuid()
    param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
    param.secretkey = Utils.encrypt(param.LText, param.timestamp)
    Api.genericInterface(param).then(res => {
      if (!res.status) {
        notification.warning({
          top: 92,
          message: res.message,
          duration: 5
        })
        return
      }
      if (res.deepseek_text) {
        sessionStorage.setItem('deepseek_sql', res.deepseek_text)
        window.open('#/ai')
        setTimeout(() => {
          sessionStorage.removeItem('deepseek_sql')
        }, 0)
      }
    })
  }
  /**
   * @description 操作失败后处理
   * 1、状态码为 E、N、F、NM 时,显示相应提示信息
@@ -2552,12 +3730,19 @@
   */
  execError = (res = {}) => {
    const { btn } = this.props
    const { autoMatic } = this.state
    const { autoMatic, dict } = this.state
    if (autoMatic) {
    if (this.preCallback) {
      this.setState({
        loading: false,
        visible: false
      })
      this.preCallback(res)
      return
    } else if (autoMatic) {
      notification.error({
        top: 92,
        message: res.message || '执行失败!',
        message: res.message || dict['exc_fail'] || '执行失败!',
        duration: 10
      })
@@ -2582,7 +3767,7 @@
      res.message = res.message.replace(/\s*<<.*>>\s*/g, '')
      val = val ? val[0].replace(/<<|>>/g, '') : ''
      if (/^http/.test(val)) {
      if (/^(http|\/\/)/.test(val)) {
        let audio = document.createElement('audio')
        audio.src = val
        audio.play()
@@ -2591,19 +3776,20 @@
      if (!res.message) {
        res.ErrCode = '-1'
      }
    } else if (/@close_tab@|@close_popup@|@goback@/i.test(res.message)) {
      sign = res.message.match(/@close_tab@|@close_popup@|@goback@/i)[0].toLowerCase()
      res.message = res.message.replace(/@close_tab@|@close_popup@|@goback@/i, '')
    } else if (/@close_tab@|@close_popup@|@goback@|@open_target_menu@/i.test(res.message)) {
      sign = res.message.match(/@close_tab@|@close_popup@|@goback@|@open_target_menu@/i)[0].toLowerCase()
      res.message = res.message.replace(/@close_tab@|@close_popup@|@goback@|@open_target_menu@/i, '')
    }
    if (res.ErrCode === 'E') {
      let msg = res.message || '执行失败!'
      let msg = res.message || dict['exc_fail'] || '执行失败!'
      if (/\n|\r/.test(msg)) {
        msg = msg.replace(/\n|\r/ig, '<br/>')
        msg = <span dangerouslySetInnerHTML={{__html: msg}}></span>
      }
      Modal.error({
        title: msg,
        okText: dict['got_it'] || '知道了',
        onOk: () => {
          this.errorContinue(sign)
        }
@@ -2612,18 +3798,25 @@
    } else if (res.ErrCode === 'N') {
      notification.error({
        top: 92,
        message: res.message || '执行失败!',
        message: res.message || dict['exc_fail'] || '执行失败!',
        duration: btn.verify && btn.verify.ntime ? btn.verify.ntime : 10
      })
    } else if (res.ErrCode === 'F') {
      notification.error({
        className: 'notification-custom-error',
        top: 92,
        message: res.message || '执行失败!',
        message: res.message || dict['exc_fail'] || '执行失败!',
        duration: btn.verify && btn.verify.ftime ? btn.verify.ftime : 10
      })
    } else if (res.ErrCode === 'NM') {
      message.error(res.message || '执行失败!')
      message.error(res.message || dict['exc_fail'] || '执行失败!')
    } else if (res.ErrCode === '-2') {
      this.setState({
        loadingNumber: '',
        loadingTotal: '',
        loading: false
      })
      return
    }
    this.errorContinue(sign)
@@ -2644,7 +3837,11 @@
      loadingTotal: '',
    })
    if (btnconfig && btnconfig.setting && btnconfig.setting.errFocus) {
    if (window.CACHE.errFocusId && (btnconfig || btn.OpenType === 'formSubmit')) {
      MKEmitter.emit('mkFC', 'focus', window.CACHE.errFocusId)
      window.CACHE.errFocusId = ''
    } else if (btnconfig && btnconfig.setting && btnconfig.setting.errFocus) {
      MKEmitter.emit('mkFC', 'focus', btnconfig.setting.errFocus)
    }
@@ -2653,8 +3850,62 @@
    } else if (btn.execError === 'closepoptab' || sign === '@close_popup@') {
      MKEmitter.emit('popclose')
    } else if (btn.execError !== 'never') {
      let tabId = ''
      if (btn.refreshTab && btn.refreshTab.length > 0) {
        tabId = btn.refreshTab[btn.refreshTab.length - 1]
      }
      if (tabId && btn.$MenuID === tabId) { // 刷新当前菜单时,停止其他操作
        MKEmitter.emit('reloadMenuView', tabId, btn.urlPar === 'true')
        return
      }
      MKEmitter.emit('refreshByButtonResult', btn.$menuId, btn.execError, btn, '', this.state.selines)
      if (btn.syncComponentId) {
        if (btn.syncComponentId === 'multiComponent') {
          if (btn.syncDelay) {
            this.delayTimer && clearTimeout(this.delayTimer)
            this.delayTimer = setTimeout(() => {
              btn.syncComponentIds.forEach((id, i) => {
                setTimeout(() => {
                  if (/\$focus/.test(id)) {
                    MKEmitter.emit('reloadData', id.split('$')[0], id.split('$')[1])
                  } else {
                    MKEmitter.emit('reloadData', id)
                  }
                }, 20 * i)
              })
            }, btn.syncDelay)
          } else {
            btn.syncComponentIds.forEach((id, i) => {
              setTimeout(() => {
                if (/\$focus/.test(id)) {
                  MKEmitter.emit('reloadData', id.split('$')[0], id.split('$')[1])
                } else {
                  MKEmitter.emit('reloadData', id)
                }
              }, 20 * i)
            })
          }
        } else if (/\$focus/.test(btn.syncComponentId)) {
          MKEmitter.emit('reloadData', btn.syncComponentId.split('$')[0], btn.syncComponentId.split('$')[1])
        } else {
          if (btn.syncDelay) {
            this.delayTimer && clearTimeout(this.delayTimer)
            this.delayTimer = setTimeout(() => {
              MKEmitter.emit('reloadData', btn.syncComponentId)
            }, btn.syncDelay)
          } else {
            MKEmitter.emit('reloadData', btn.syncComponentId)
          }
        }
      }
      if (tabId) {
        MKEmitter.emit('reloadMenuView', tabId, btn.urlPar === 'true')
      }
    }
    if (btn.OpenType === 'form') {
      let data = this.props.selectedData && this.props.selectedData[0] ? this.props.selectedData[0] : null
@@ -2675,6 +3926,35 @@
    if (window.GLOB.breakpoint) {
      MKEmitter.emit('refreshDebugTable')
    }
    if (sign === '@open_target_menu@' && btn.openmenu && Array.isArray(btn.openmenu) && btn.openmenu.length > 0) {
      let id = ''
      if (this.state.selines && this.state.selines.length > 0 && btn.Ot !== 'notRequired') {
        if (btn.Ot === 'requiredOnce') {
          id = this.state.selines.map(d => d.$$uuid).filter(Boolean).join(',')
        } else {
          id = this.state.selines[0].$$uuid
        }
      }
      let menuId = btn.openmenu.slice(-1)[0]
      let menu = null
      if (window.GLOB.mkThdMenus.has(menuId)) {
        menu = {...window.GLOB.mkThdMenus.get(menuId), param: { $BID: id || '' }}
      } else if (btn.MenuID) {
        menu = {
          MenuID: btn.MenuID,
          MenuName: btn.MenuName,
          type: btn.tabType,
          param: { $BID: id || '' }
        }
      }
      if (menu) {
        MKEmitter.emit('modifyTabs', menu, true)
      }
    }
    if (btn.execError === 'popclose' && btn.$tabId) { // 标签关闭刷新
@@ -2785,11 +4065,11 @@
  /**
   * @description 模态框(表单),确认
   */
  handleOk = () => {
  handleOk = (submitType = '') => {
    if (!this.formRef) return
    
    this.formRef.handleConfirm().then(res => {
      this.setState({ confirmLoading: true })
      this.setState({ confirmLoading: true, submitType: submitType })
      this.execSubmit(this.state.selines, () => { this.setState({ confirmLoading: false }) }, res)
    })
@@ -2802,14 +4082,17 @@
    this.setState({
      loading: false,
      visible: false,
      confirmLoading: false
      confirmLoading: false,
      submitType: ''
    })
    this.preCallback && this.preCallback()
  }
  modelconfirm = () => {
    const { btn, BID } = this.props
    const { btnconfig, selines } = this.state
    let _this = this
    const { BID } = this.props
    const { btnconfig, selines, dict } = this.state
    let that = this
    let result = []
    let _data = {}
@@ -2842,6 +4125,10 @@
      let key = item.field.toLowerCase()
      let _readin = item.readin !== 'false'
      if (item.type === 'linkMain' && item.verifyVal === 'true') {
        _item.$verify = true
        _item.label = item.label
      }
      if (_item.type === 'date') { // 时间兼容
        _item.precision = item.precision || 'day'
      } else if (_item.type === 'datetime') {
@@ -2892,12 +4179,31 @@
              console.warn(e)
              _item.value = ''
            }
          } else if (item.interception === 'charTure') {
            let str = _item.value.replace(/(^\s*|\s*$)/g, '')
            let result = ''
            for (let i = 0 ; i < str.length; i++) {
              let code = str.charCodeAt(i)
              if (code >= 65281 && code <= 65373) {
                result += String.fromCharCode(str.charCodeAt(i) - 65248)
              } else if (code === 12288) {
                result += String.fromCharCode(str.charCodeAt(i) - 12288 + 32)
              } else {
                result += str.charAt(i)
              }
            }
            _item.value = result
          } else {
            _item.value = _item.value.replace(/(^\s*|\s*$)/g, '')
          }
        }
        if (_item.type === 'text' && /@appkey@|@SessionUid@|@bid@/ig.test(_item.value)) { // 特殊字段替换
          _item.value = _item.value.replace(/^(\s*)@appkey@(\s*)$/ig, window.GLOB.appkey).replace(/^(\s*)@SessionUid@(\s*)$/ig, (localStorage.getItem('SessionUid') || '')).replace(/^(\s*)@bid@(\s*)$/ig, (BID || ''))
        if (_item.type === 'text') {
          if (/@appkey@|@SessionUid@|@bid@/ig.test(_item.value)) { // 特殊字段替换
            _item.value = _item.value.replace(/^(\s*)@appkey@(\s*)$/ig, window.GLOB.appkey).replace(/^(\s*)@SessionUid@(\s*)$/ig, (localStorage.getItem('SessionUid') || '')).replace(/^(\s*)@bid@(\s*)$/ig, (BID || ''))
          }
          if (/@currentYear@/ig.test(_item.value)) { // 系统变量替换
            _item.value = _item.value.replace(/@currentYear@/ig, moment().format('YYYY'))
          }
        }
        if (_item.type === 'text' && item.lenControl && item.lenControl !== 'limit') {
          if (item.lenControl === 'left') {
@@ -2938,14 +4244,17 @@
      this.execSubmit(selines, () => {}, result)
    } else {
      confirm({
        title: btn.tipTitle || '确定要执行吗?',
        title: btnconfig.setting.tipTitle || dict['exec_sure'] || '确定要执行吗?',
        okText: dict['ok'] || '确定',
        cancelText: dict['cancel'] || '取消',
        onOk() {
          return new Promise(resolve => {
            _this.execSubmit(selines, resolve, result)
            that.execSubmit(selines, resolve, result)
          })
        },
        onCancel() {
          _this.setState({ loading: false })
          that.preCallback && that.preCallback()
          that.setState({ loading: false })
        }
      })
    }
@@ -2956,13 +4265,14 @@
   */
  getModels = () => {
    const { BID, btn, BData } = this.props
    const { btnconfig, visible } = this.state
    const { btnconfig, visible, dict, confirmLoading, submitType, loadingNumber, loadingTotal } = this.state
    if (!btnconfig || !btnconfig.setting) return null
    let title = btn.label
    let width = btnconfig.setting.width > 100 ? btnconfig.setting.width : btnconfig.setting.width + 'vw'
    let clickouter = btnconfig.setting.clickouter === 'close'
    let num = loadingNumber && !loadingTotal ? `(${loadingNumber}) ` : ''
    if (btnconfig.setting.display === 'drawer') {
      let height = '100vh'
@@ -2985,19 +4295,23 @@
          <MutilForm
            BID={BID}
            action={btnconfig}
            inputSubmit={this.handleOk}
            inputSubmit={() => this.handleOk()}
            data={this.state.selines[0]}
            BData={BData}
            wrappedComponentRef={(inst) => this.formRef = inst}
          />
          <div className="ant-drawer-footer" style={{ position: 'absolute', zIndex: 1, right: 0, bottom: 0, width: '100%', borderTop: '1px solid #e9e9e9', padding: '10px 16px', background: '#fff', textAlign: 'right'}}>
          {btnconfig.setting.formType === 'check' ? <div className="ant-drawer-footer" style={{ position: 'absolute', zIndex: 1, right: 0, bottom: 0, width: '100%', borderTop: '1px solid #e9e9e9', padding: '10px 16px', background: '#fff', textAlign: 'right'}}>
            <Button onClick={this.handleCancel} style={{ marginRight: 8 }}>
              {btnconfig.setting.formType !== 'check' ? '取消' : '关闭'}
              {dict['close'] || '关闭'}
            </Button>
            {btnconfig.setting.formType !== 'check' ? <Button onClick={this.handleOk} loading={this.state.confirmLoading} type="primary">
              确定
            </Button> : null}
          </div>
          </div> : <div className="ant-drawer-footer" style={{ position: 'absolute', zIndex: 1, right: 0, bottom: 0, width: '100%', borderTop: '1px solid #e9e9e9', padding: '10px 16px', background: '#fff', textAlign: 'right'}}>
            <Button onClick={this.handleCancel} style={{ marginRight: 8 }}>
              {dict['cancel'] || '取消'}
            </Button>
            {btn.extBtn === 'true' ? <Button className={'extend-btn ' + (btn.extStyle || '')} disabled={confirmLoading && submitType !== btn.extValue} loading={confirmLoading && submitType === btn.extValue} onClick={() => this.handleOk(btn.extValue)}>{btn.extLabel}</Button> : null}
            {btn.extBtn === 'true' ? <Button className={'confirm-btn ' + (btn.confStyle || '')} disabled={confirmLoading && submitType !== ''} loading={confirmLoading && submitType === ''} onClick={() => this.handleOk()}>{btn.confLabel || dict['ok'] || '确定'}</Button> : null}
            {btn.extBtn !== 'true' ? <Button type="primary" loading={confirmLoading} onClick={() => this.handleOk()}>{dict['ok'] || '确定'}</Button> : null}
          </div>}
        </Drawer>
      )
    } else {
@@ -3023,16 +4337,20 @@
          wrapClassName={'action-modal' + (btnconfig.setting.moveable === 'true' ? ' moveable-modal modal-' + btn.uuid : '')}
          visible={visible}
          width={width}
          onOk={this.handleOk}
          maskStyle={btnconfig.setting.moveable === 'true' ?  {backgroundColor: 'rgba(0, 0, 0, 0.15)'} : null}
          confirmLoading={this.state.confirmLoading}
          onCancel={this.handleCancel}
          footer={[
            <Button key="cancel" onClick={this.handleCancel}>{dict['cancel'] || '取消'}</Button>,
            btn.extBtn === 'true' ? <Button key="extend" className={'extend-btn ' + (btn.extStyle || '')} disabled={confirmLoading && submitType !== btn.extValue} loading={confirmLoading && submitType === btn.extValue} onClick={() => this.handleOk(btn.extValue)}>{submitType === btn.extValue ? num : ''}{btn.extLabel}</Button> : null,
            btn.extBtn === 'true' ? <Button key="confirm" className={'confirm-btn ' + (btn.confStyle || '')} disabled={confirmLoading && submitType !== ''} loading={confirmLoading && submitType === ''} onClick={() => this.handleOk()}>{submitType === '' ? num : ''}{btn.confLabel || dict['ok'] || '确定'}</Button> : null,
            btn.extBtn !== 'true' ? <Button key="confirm" type="primary" loading={confirmLoading} onClick={() => this.handleOk()}>{num}{dict['ok'] || '确定'}</Button> : null
          ]}
          destroyOnClose
        >
          <MutilForm
            BID={BID}
            action={btnconfig}
            inputSubmit={this.handleOk}
            inputSubmit={() => this.handleOk()}
            data={this.state.selines[0]}
            BData={BData}
            wrappedComponentRef={(inst) => this.formRef = inst}
@@ -3087,7 +4405,7 @@
  changeLineCount = (count) => {
    const { btn, selectedData } = this.props
    const { disabled } = this.state
    const { disabled, dict } = this.state
    if (disabled) return
@@ -3097,7 +4415,7 @@
      // 需要选择行时,校验数据
      notification.warning({
        top: 92,
        message: '请选择行!',
        message: dict['select_row'] || '请选择行!',
        duration: 5
      })
      return
@@ -3105,7 +4423,7 @@
      // 需要选择单行时,校验数据
      notification.warning({
        top: 92,
        message: '请选择单行数据!',
        message: dict['select_single_row'] || '请选择单行数据!',
        duration: 5
      })
      return
@@ -3117,7 +4435,7 @@
  }
  render() {
    const { btn } = this.props
    const { btn, name } = this.props
    const { loadingNumber, loadingTotal, loading, disabled, hidden, check, count } = this.state
    if (hidden) return null
@@ -3136,45 +4454,36 @@
    }
    let label = ''
    let icon = ''
    let type = 'link'
    let className = ''
    if (btn.show === 'button') {
      label = btn.label
      icon = btn.icon || ''
    } else if (btn.show === 'link') {
      label = <span>{btn.label}{btn.icon ? <MkIcon style={{marginLeft: '8px'}} type={btn.icon}/> : ''}</span>
      icon = ''
    if (btn.show === 'link') {
      label = <span>{name || btn.label}{btn.icon ? <MkIcon style={{marginLeft: '8px'}} type={btn.icon} /> : ''}</span>
    } else if (btn.show === 'icon') {
      icon = btn.icon || ''
    } else if (!btn.$toolbtn) {
      icon = btn.icon || ''
      label = btn.label
      className = 'mk-btn mk-' + (btn.class || 'unset')
      label = !loading ? <MkIcon type={btn.icon} /> : null
    } else if (btn.$toolbtn) {
      label = <span>{!loading && btn.icon ? <MkIcon style={{marginRight: '8px'}} type={btn.icon} /> : ''}{loadingNumber && !loadingTotal ? `(${loadingNumber})` : ''}{btn.label}</span>
    } else {
      type = ''
      icon = btn.icon || ''
      label = btn.label
      className = 'mk-btn mk-' + (btn.class || 'unset')
      label = <span>{!loading && btn.icon ? <MkIcon style={{marginRight: '8px'}} type={btn.icon} /> : ''}{name || btn.label}</span>
    }
    if (loadingNumber && btn.progress !== 'progressbar' && btn.$toolbtn && (!btn.show || btn.show === 'button')) {
      label = (loadingNumber ? `(${loadingNumber})` : '') + btn.label
    let BTN = <Button
      type="link"
      id={'button' + btn.uuid}
      title={disabled ? (btn.reason || '') : (btn.show === 'icon' ? btn.label : '')}
      loading={loading}
      disabled={disabled}
      style={btn.style}
      className={btn.hover || ''}
      onClick={(e) => {e.stopPropagation(); this.actionTrigger()}}
    >{label}</Button>
    if (btn.hoverTitle) {
      BTN = <Popover mouseLeaveDelay={0.3} mouseEnterDelay={0.3} content={btn.hoverTitle} trigger="hover">
        {BTN}
      </Popover>
    }
    return <>
      <Button
        type={type}
        icon={icon}
        id={'button' + btn.uuid}
        title={disabled ? (btn.reason || '') : (btn.show === 'icon' ? btn.label : '')}
        loading={loading}
        disabled={disabled}
        style={btn.style}
        className={className}
        onClick={(e) => {e.stopPropagation(); this.actionTrigger()}}
      >{label}</Button>
      {BTN}
      <span onClick={(e) => {e.stopPropagation()}}>{this.getModels()}</span>
      {loadingTotal ? <Progress className="mk-button-progress" percent={(loadingTotal - loadingNumber) / loadingTotal * 100} size="small" showInfo={false} /> : null}
    </>