king
2024-06-28 c8804ceb1fe2dea76f9949c5ea04423876ee2c81
2024-06-28
39个文件已修改
4个文件已添加
2101 ■■■■ 已修改文件
public/README.txt 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/index.js 40 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/header/index.jsx 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/index.js 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/card/cardcellcomponent/dragaction/action.jsx 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/card/cardcellcomponent/index.jsx 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/share/actioncomponent/actionform/index.jsx 80 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/share/actioncomponent/dragaction/card.jsx 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/share/actioncomponent/formconfig.jsx 149 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/share/actioncomponent/index.jsx 9 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/debug/index.jsx 54 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/tablenodes/index.jsx 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/transfer/index.jsx 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/mob/header/index.jsx 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/mob/header/index.scss 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/card/cardcellList/index.jsx 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/actionList/funcbutton/index.jsx 202 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/actionList/index.jsx 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/actionList/newpagebutton/index.jsx 282 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/actionList/normalbutton/index.jsx 15 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/actioncomponent/verifypay/customscript/index.jsx 224 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/actioncomponent/verifypay/customscript/index.scss 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/actioncomponent/verifypay/index.jsx 516 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/actioncomponent/verifypay/index.scss 84 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/actioncomponent/verifyprint/index.jsx 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/searchcomponent/searchform/index.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/zshare/verifycard/baseform/index.jsx 133 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/zshare/verifycard/fullScripts/index.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/zshare/verifycard/index.jsx 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/utils-custom.js 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/appcheck/index.jsx 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/appmanage/index.jsx 72 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/appmanage/submutilform/index.jsx 36 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/appmanage/transmenu/index.jsx 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/design/header/index.jsx 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/design/header/transmenu/index.jsx 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/design/sidemenu/thdmenuplus/index.jsx 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/menudesign/index.jsx 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mkiframe/index.jsx 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mobdesign/index.jsx 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/pay/index.jsx 80 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/pcdesign/index.jsx 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/tabledesign/index.jsx 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
public/README.txt
@@ -11,6 +11,8 @@
defaultLang       -- 打开的子应用语言类型,默认为zh-CN
WXAppID           -- 使用公众号时,绑定的公众号ID
WXminiAppID       -- 使用微信小程序时,绑定的小程序ID
WXNotice          -- 是否开启明科云公众号消息提醒,值为 true 时开启,可通过明科云发送模板消息
WXApps            -- 存在多个公众号或小程序时可使用微信APP列表,注意填写默认公众号或小程序,[{"appId": "", "appName": "", "appType": "public/miniProgram"}]
nginx             -- 是否开启了nginx服务,值为 true 时开启,如需使用微信模板消息等服务,请先设置nginx服务并开启此配置
debugger          -- 值为 true 时开启调试模式,开启后移动端子应用中会有控制台
licenseKey        -- 许可密钥,在内部网络中使用系统时,会跳过epc验证
src/api/index.js
@@ -100,18 +100,18 @@
  /**
   * @description 微信业务请求 原接口 'wxpay/getaccesstoken'
   */
  wxAccessToken (domain = '') {
  wxAccessToken (appId, domain = '') {
    let _url = domain || window.GLOB.baseurl
    return new Promise(resolve => {
      if (window.GLOB.accessToken.domain === domain && window.GLOB.accessToken.accessTime && (parseInt(new Date().getTime() / 1000) - window.GLOB.accessToken.accessTime < 30)) {
      if (window.GLOB.accessToken.appId === appId && window.GLOB.accessToken.accessTime && (parseInt(new Date().getTime() / 1000) - window.GLOB.accessToken.accessTime < 30)) {
        resolve(window.GLOB.accessToken)
      } else {
        window.GLOB.accessToken = {domain}
        window.GLOB.accessToken = {appId}
        axios({
          url: _url + 'wechat/getaccesstoken',
          method: 'post',
          data: JSON.stringify({app_id: domain === '' ? window.GLOB.WXAppID : 'wx4d8a34c8d4494872'})
          data: JSON.stringify({app_id: appId})
        }).then(res => {
          if (res.access_token) {
            window.GLOB.accessToken.accessTime = parseInt(new Date().getTime() / 1000)
@@ -135,12 +135,12 @@
      if (process.env.NODE_ENV === 'production') {
        _url = document.location.origin + '/' + url
      }
      if (/qingqiumarket.cn|cloud.mk9h.cn/.test(_url)) {
        _url = _url.replace('http://qingqiumarket.cn/', 'http://qingqiumarket.cn:8080/')
        _url = _url.replace('http://cloud.mk9h.cn/', 'http://cloud.mk9h.cn:8080/')
        _url = _url.replace('https://qingqiumarket.cn/', 'https://qingqiumarket.cn:8443/')
        _url = _url.replace('https://cloud.mk9h.cn/', 'https://cloud.mk9h.cn:8443/')
      }
    }
    if (/qingqiumarket.cn|cloud.mk9h.cn/.test(_url)) {
      _url = _url.replace('http://qingqiumarket.cn/', 'http://qingqiumarket.cn:8080/')
      _url = _url.replace('http://cloud.mk9h.cn/', 'http://cloud.mk9h.cn:8080/')
      _url = _url.replace('https://qingqiumarket.cn/', 'https://qingqiumarket.cn:8443/')
      _url = _url.replace('https://cloud.mk9h.cn/', 'https://cloud.mk9h.cn:8443/')
    }
    
    if (param) {
@@ -1037,30 +1037,24 @@
  }
  /**
   * @description 获取微信支付二维码
   * @description 获取微信支付二维码 原接口wxpay/wxNativePay
   */
  getWxNativePay (param) {
    let _url = window.GLOB.baseurl + 'wxpay/wxNativePay'
    return axios({
      url: _url,
      url: window.GLOB.baseurl + 'wechat/native',
      method: 'post',
      data: qs.stringify(param)
      data: JSON.stringify(param)
    })
  }
  /**
   * @description 微信支付退款
   * @description 微信支付退款 原接口wxpay/wxRefund
   */
  setRefund (orderId) {
    let _param = new FormData()
    _param.append('out_biz_no', orderId)
  setRefund (param) {
    return axios({
      url: '/wxpay/wxRefund',
      headers: { 'Content-Type': 'multipart/form-data' },
      url: window.GLOB.baseurl + 'wechat/wxRefund',
      method: 'post',
      data: _param
      data: JSON.stringify(param)
    })
  }
src/components/header/index.jsx
@@ -109,6 +109,7 @@
      setTimeout(() => {
        sessionStorage.clear()
        this.props.history.replace('/login')
        window.location.reload()
      }, 2000)
    })
  }
src/index.js
@@ -59,6 +59,13 @@
    GLOB.style = 'bg_black_style_blue'
    GLOB.defLang = ''
    if (config.WXApps) {
      config.WXApps = config.WXApps.filter(app => app.appId && app.appName && ['public', 'miniProgram'].includes(app.appType))
      if (config.WXApps.length) {
        GLOB.WXApps = config.WXApps
      }
    }
    if (langs[config.defaultLang]) {
      GLOB.defLang = config.defaultLang
    }
src/menu/components/card/cardcellcomponent/dragaction/action.jsx
@@ -48,6 +48,8 @@
    hasProfile = true
  } else if (card.OpenType === 'innerpage' && !card.pageTemplate) {
    warning = <WarningOutlined style={{color: 'orange', marginLeft: '5px'}}/>
  } else if (card.payMode === 'system') {
    hasProfile = true
  }
  let btnElement = null
src/menu/components/card/cardcellcomponent/index.jsx
@@ -21,6 +21,7 @@
const VerifyPrint = asyncComponent(() => import('@/templates/sharecomponent/actioncomponent/verifyprint'))
const VerifyExcelIn = asyncComponent(() => import('@/templates/sharecomponent/actioncomponent/verifyexcelin'))
const VerifyExcelOut = asyncComponent(() => import('@/templates/sharecomponent/actioncomponent/verifyexcelout'))
const VerifyPay = asyncComponent(() => import('@/templates/sharecomponent/actioncomponent/verifypay'))
class CardCellComponent extends Component {
  static propTpyes = {
@@ -806,6 +807,12 @@
        columns={side === 'sub' ? cards.subColumns : cards.columns}
        wrappedComponentRef={(inst) => this.verifyRef = inst}
      />
    } else if (card.payMode === 'system') {
      return <VerifyPay
        card={card}
        columns={side === 'sub' ? cards.subColumns : cards.columns}
        wrappedComponentRef={(inst) => this.verifyRef = inst}
      />
    }
  }
src/menu/components/share/actioncomponent/actionform/index.jsx
@@ -443,6 +443,15 @@
        reOptions.Ot = requireOptions
      } else if (this.record.pageTemplate === 'pay') {
        reOptions.Ot = requireOptions.filter(op => op.value === 'requiredSgl')
        shows.push('payMode', 'wxApp')
        if (this.record.payMode === 'inner') {
          reRequired.innerFunc = true
          shows.push('innerFunc')
        }
        if (this.record.payMode !== 'none') {
          shows.push('output')
        }
      }
    } else if (openType === 'funcbutton') {
      reOptions.intertype = this.state.interTypeOptions.filter(op => op.value !== 'custom')
@@ -511,14 +520,31 @@
        shows.push('innerFunc', 'Ot', 'execSuccess', 'execError', 'urlkey')
      } else if (_funcType === 'pay') {
        shows.push('payType', 'Ot', 'execSuccess', 'execError', 'syncComponent', 'openmenu')
        shows.push('payType', 'wxApp', 'Ot', 'execSuccess', 'execError', 'syncComponent', 'openmenu')
        if (this.record.openmenu && this.record.openmenu !== 'goback') {
          shows.push('open')
        }
        reOptions.Ot = requireOptions.filter(op => ['requiredSgl'].includes(op.value))
        shows.push('payMode')
        if (this.record.payMode === 'inner') {
          reRequired.innerFunc = true
          shows.push('innerFunc')
        }
        if (this.record.payMode !== 'none') {
          shows.push('output')
        }
      } else if (_funcType === 'refund') {
        shows.push('Ot', 'execSuccess', 'execError', 'syncComponent', 'openmenu', 'tipTitle')
        shows.push('Ot', 'wxApp', 'execSuccess', 'execError', 'syncComponent', 'openmenu', 'tipTitle')
        reOptions.Ot = requireOptions.filter(op => ['requiredSgl'].includes(op.value))
        shows.push('payMode')
        if (this.record.payMode === 'inner') {
          reRequired.innerFunc = true
          shows.push('innerFunc')
        }
        if (this.record.payMode !== 'none') {
          shows.push('output')
        }
      } else if (_funcType === 'shareLink') {
        shows.push('shortUrl', 'shareUrl', 'shareProUrl', 'shareTip')
      // } else if (_funcType === 'expPdf') {
@@ -856,22 +882,42 @@
            { max: 512, message: '最多512个字符' }
          )
        } else if (item.key === 'output') {
          if (this.record.intertype === 'system' || ((this.record.intertype === 'outer' || this.record.intertype === 'custom') && this.record.callbackType === 'script')) {
            rules = [{
              pattern: /^@[0-9a-zA-Z_]+@?$/,
              message: '变量以@符开头,可使用字母、数字以及_'
            }, {
              max: 100,
              message: '最多100个字符。'
            }]
          if (['pop', 'prompt', 'exec'].includes(this.record.openType)) {
            if (this.record.intertype === 'system' || ((this.record.intertype === 'outer' || this.record.intertype === 'custom') && this.record.callbackType === 'script')) {
              rules = [{
                pattern: /^@[0-9a-zA-Z_]+@?$/,
                message: '变量以@符开头,可使用字母、数字以及_'
              }, {
                max: 100,
                message: '最多100个字符。'
              }]
            } else {
              rules = [{
                pattern: /^[0-9a-zA-Z_]*$/,
                message: '字段可使用字母、数字以及_'
              }, {
                max: 100,
                message: '最多100个字符。'
              }]
            }
          } else {
            rules = [{
              pattern: /^[0-9a-zA-Z_]*$/,
              message: '字段可使用字母、数字以及_'
            }, {
              max: 100,
              message: '最多100个字符。'
            }]
            if (this.record.payMode === 'system') {
              rules = [{
                pattern: /^@[0-9a-zA-Z_]+@?$/,
                message: '变量以@符开头,可使用字母、数字以及_'
              }, {
                max: 100,
                message: '最多100个字符。'
              }]
            } else {
              rules = [{
                pattern: /^[0-9a-zA-Z_]*$/,
                message: '字段可使用字母、数字以及_'
              }, {
                max: 100,
                message: '最多100个字符。'
              }]
            }
          }
        } else {
          rules.push({ max: formRule.input.max, message: formRule.input.message })
src/menu/components/share/actioncomponent/dragaction/card.jsx
@@ -46,6 +46,8 @@
    hasProfile = true
  } else if (card.funcType === 'megvii') {
    hasProfile = true
  } else if (card.payMode === 'system') {
    hasProfile = true
  }
  let btnElement = null
src/menu/components/share/actioncomponent/formconfig.jsx
@@ -222,6 +222,7 @@
    opentypes = opentypes.filter(item => item.value !== 'tab')
    funTypes = [
      { value: 'print', text: '标签打印' },
      { value: 'refund', text: '退款' },
    ]
    pageTemps = [
      { value: 'linkpage', text: '关联菜单' },
@@ -421,20 +422,20 @@
      required: true,
      options: []
    },
    {
      type: 'checkbox',
      key: 'payType',
      label: '支付方式',
      initVal: card.payType || [],
      required: true,
      options: [{
        value: 'wxpay',
        text: '微信'
      // }, {
      //   value: 'alipay',
      //   text: '支付宝'
      }]
    },
    // {
    //   type: 'checkbox',
    //   key: 'payType',
    //   label: '支付方式',
    //   initVal: card.payType || [],
    //   required: true,
    //   options: [{
    //     value: 'wxpay',
    //     text: '微信'
    //   // }, {
    //   //   value: 'alipay',
    //   //   text: '支付宝'
    //   }]
    // },
    {
      type: 'radio',
      key: 'procMode',
@@ -470,15 +471,6 @@
    },
    {
      type: 'text',
      key: 'innerFunc',
      label: '内部函数',
      initVal: card.innerFunc || '',
      tooltip: functip,
      fields: usefulFields,
      required: false,
    },
    {
      type: 'text',
      key: 'urlkey',
      label: '地址字段',
      initVal: card.urlkey || '',
@@ -493,6 +485,43 @@
      initVal: card.pageTemplate || '',
      required: true,
      options: pageTemps
    },
    {
      type: 'radio',
      key: 'payMode',
      label: '参数处理',
      initVal: card.payMode || 'none',
      tooltip: '支付(或退款)单号的预处理方式。',
      required: true,
      options: [{
        value: 'system',
        text: '系统函数'
      }, {
        value: 'inner',
        text: '内部函数'
      }, {
        value: 'none',
        text: '无'
      }]
    },
    {
      type: 'select',
      key: 'wxApp',
      label: '关联应用',
      initVal: card.wxApp || '',
      tooltip: '请关联支付(或退款)的公众号或小程序。',
      required: true,
      forbid: !!appType || !window.GLOB.WXApps,
      options: window.GLOB.WXApps ? window.GLOB.WXApps.map(item => ({value: item.appId, text: item.appName})) : []
    },
    {
      type: 'text',
      key: 'innerFunc',
      label: '内部函数',
      initVal: card.innerFunc || '',
      tooltip: functip,
      fields: usefulFields,
      required: false,
    },
    {
      type: 'printTemps',
@@ -1795,20 +1824,20 @@
      required: true,
      options: []
    },
    {
      type: 'checkbox',
      key: 'payType',
      label: '支付方式',
      initVal: card.payType || [],
      required: true,
      options: [{
        value: 'wxpay',
        text: '微信'
      // }, {
      //   value: 'alipay',
      //   text: '支付宝'
      }]
    },
    // {
    //   type: 'checkbox',
    //   key: 'payType',
    //   label: '支付方式',
    //   initVal: card.payType || [],
    //   required: true,
    //   options: [{
    //     value: 'wxpay',
    //     text: '微信'
    //   // }, {
    //   //   value: 'alipay',
    //   //   text: '支付宝'
    //   }]
    // },
    {
      type: 'radio',
      key: 'procMode',
@@ -1844,15 +1873,6 @@
    },
    {
      type: 'text',
      key: 'innerFunc',
      label: '内部函数',
      initVal: card.innerFunc || '',
      tooltip: functip,
      fields: usefulFields,
      required: false,
    },
    {
      type: 'text',
      key: 'urlkey',
      label: '地址字段',
      initVal: card.urlkey || '',
@@ -1869,6 +1889,43 @@
      options: pageTemps
    },
    {
      type: 'radio',
      key: 'payMode',
      label: '参数处理',
      initVal: card.payMode || 'none',
      tooltip: '支付(或退款)单号的预处理方式。',
      required: true,
      options: [{
        value: 'system',
        text: '系统函数'
      }, {
        value: 'inner',
        text: '内部函数'
      }, {
        value: 'none',
        text: '无'
      }]
    },
    {
      type: 'select',
      key: 'wxApp',
      label: '关联应用',
      initVal: card.wxApp || '',
      tooltip: '请关联支付(或退款)的公众号或小程序。',
      required: true,
      forbid: !window.GLOB.WXApps,
      options: window.GLOB.WXApps ? window.GLOB.WXApps.map(item => ({value: item.appId, text: item.appName})) : []
    },
    {
      type: 'text',
      key: 'innerFunc',
      label: '内部函数',
      initVal: card.innerFunc || '',
      tooltip: functip,
      fields: usefulFields,
      required: false,
    },
    {
      type: 'printTemps',
      key: 'printTemp',
      label: '打印模板',
src/menu/components/share/actioncomponent/index.jsx
@@ -20,6 +20,7 @@
const VerifyExcelIn = asyncSpinComponent(() => import('@/templates/sharecomponent/actioncomponent/verifyexcelin'))
const VerifyExcelOut = asyncSpinComponent(() => import('@/templates/sharecomponent/actioncomponent/verifyexcelout'))
const VerifyMegvii = asyncSpinComponent(() => import('@/templates/sharecomponent/actioncomponent/verifymegvii'))
const VerifyPay = asyncSpinComponent(() => import('@/templates/sharecomponent/actioncomponent/verifypay'))
class ActionComponent extends Component {
  static propTpyes = {
@@ -524,7 +525,7 @@
  verifySubmit = () => {
    const { config } = this.props
    const { card } = this.state
    this.verifyRef.handleConfirm().then(res => {
      let _actionlist = fromJS(this.state.actionlist).toJS()
      _actionlist = _actionlist.filter(item => !item.origin || item.uuid === card.uuid)
@@ -698,6 +699,12 @@
        columns={config.columns}
        wrappedComponentRef={(inst) => this.verifyRef = inst}
      />
    } else if (card.payMode === 'system') {
      return <VerifyPay
        card={card}
        columns={config.columns}
        wrappedComponentRef={(inst) => this.verifyRef = inst}
      />
    }
  }
src/menu/debug/index.jsx
@@ -439,6 +439,12 @@
    } else if (cell.OpenType === 'funcbutton') {
      if (cell.funcType === 'print') {
      } else if ((cell.funcType === 'refund' || cell.funcType === 'pay') && cell.payMode === 'system') {
        sql = this.getPaySql(cell, item)
      }
    } else if (cell.OpenType === 'innerpage' || cell.OpenType === 'outerpage') {
      if (cell.pageTemplate === 'pay' && cell.payMode === 'system') {
        sql = this.getPaySql(cell, item)
      }
    } else if (cell.OpenType === 'popview') {
      if (cell.config && cell.config.components) {
@@ -1896,6 +1902,54 @@
    return sql
  }
  getPaySql = (btn, component) => {
    let sysfields = ['username', 'fullname', 'roleid', 'mk_departmentcode', 'mk_organization', 'mk_user_type', 'mk_nation', 'mk_province', 'mk_city', 'mk_district', 'mk_address', 'tbid', 'bid']
    let _declare = []
    let _select = []
    component.columns.forEach(_f => {
      if (sysfields.includes(_f.field.toLowerCase())) return
      if (/decimal|int/ig.test(_f.datatype)) {
        _select.push(`@${_f.field}=1`)
      } else if (/date/ig.test(_f.datatype)) {
        _select.push(`@${_f.field}='1949-10-01'`)
      } else {
        _select.push(`@${_f.field}=''`)
      }
      _declare.push(`@${_f.field} ${_f.datatype}`)
    })
    _declare = _declare.join(', ')
    _select = _select.join(', ')
    let _sql = `Declare @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), @ErrorCode nvarchar(50), @retmsg nvarchar(4000), @bid nvarchar(50), @tbid nvarchar(50), ${_declare}
    Select @UserName='', @FullName='', @RoleID='', @mk_departmentcode='', @mk_organization='', @mk_user_type='', @mk_nation='', @mk_province='', @mk_city='', @mk_district='', @mk_address='', @ErrorCode='', @retmsg='', @bid='', ${_select}
    `
    btn.verify.scripts.forEach(item => {
      if (item.status === 'false') return
      _sql += `
      ${item.sql}
      `
    })
    if (btn.output) {
      _sql += `
        aaa: select @ErrorCode as ErrorCode,@retmsg as retmsg,${btn.output} as mk_b_id`
    } else {
      _sql += `
        aaa: select @ErrorCode as ErrorCode,@retmsg as retmsg`
    }
    _sql = _sql.replace(/@typename@/ig, `'typename'`)
    _sql = _sql.replace(/@\$|\$@/ig, '').replace(/@datam@/ig, `''`)
    return _sql
  }
  formatDataSource = (item, regs, mainSearch = []) => {
    if (!item.setting || item.setting.interType !== 'system') return false
    
src/menu/tablenodes/index.jsx
@@ -485,9 +485,12 @@
                if (m.debug_url) {
                  let _param = JSON.parse(window.decodeURIComponent(window.atob(m.debug_url)))
                  let label = _param.MenuName
                  _param.lang = _param.lang || 'zh-CN'
                  if (_param && _param.type === 'app') {
                    label += ` (${_param.kei_no} | ${_param.typename}${param.lang !== 'zh-CN' ? ' | ' + param.lang : ''})`
                    label += ` (${_param.kei_no} | ${_param.typename}${_param.lang !== 'zh-CN' ? ' | ' + _param.lang : ''})`
                  } else if (_param && _param.lang && _param.lang !== 'zh-CN') {
                    label += ` (${_param.lang})`
                  }
                  cell.children.push({
@@ -534,7 +537,7 @@
      }, 50)
    } else if (menu.param) {
      if (menu.param.type === 'admin') {
        if (menu.param.MenuType === 'custom') {
        if (['custom', 'home', 'billPrint'].includes(menu.param.MenuType)) {
          let _param = {...menu.param}
          delete _param.type
          _param = window.btoa(window.encodeURIComponent(JSON.stringify(_param)))
@@ -548,11 +551,11 @@
        }
      } else if (menu.param.type === 'app') {
        if (menu.param.typename !== 'pc') {
          let _param = {...menu.param, lang: sessionStorage.getItem('lang')}
          let _param = {...menu.param}
          _param = window.btoa(window.encodeURIComponent(JSON.stringify(_param)))
          window.open(`#/mobdesign/${_param}`)
        } else {
          let _param = {...menu.param, lang: sessionStorage.getItem('lang')}
          let _param = {...menu.param}
          _param = window.btoa(window.encodeURIComponent(JSON.stringify(_param)))
          window.open(`#/pcdesign/${_param}`)
        }
src/menu/transfer/index.jsx
@@ -218,7 +218,8 @@
      type: 'admin',
      OpenType: _config.OpenType,
      PageParam: {Template: 'CustomPage', OpenType: 'newtab', hidden: _config.hidden},
      MenuType: 'custom'
      MenuType: 'custom',
      lang: sessionStorage.getItem('lang')
    }
    let url = window.btoa(window.encodeURIComponent(JSON.stringify(urlparam)))
src/mob/header/index.jsx
@@ -1,5 +1,6 @@
import React, {Component} from 'react'
import { langs } from '@/store/options.js'
import avatar from '@/assets/img/avatar.jpg'
import MainLogo from '@/assets/img/main-logo.png'
import './index.scss'
@@ -13,10 +14,13 @@
  render () {
    const { logo } = this.state
    let lang = sessionStorage.getItem('lang')
    lang = lang !== 'zh-CN' ? langs[lang] || '' : ''
    return (
      <header className="mob-header-container">
        <div className="header-logo"><img src={logo} alt=""/></div>
        <span className="lang">{lang}</span>
        <div className="header-user">
          <img src={this.state.avatar} alt=""/>
          <span>
src/mob/header/index.scss
@@ -9,6 +9,13 @@
  background: #001529;
  border-bottom: 1px solid #000;
  .lang {
    position: absolute;
    font-size: 18px;
    left: calc(50% - 12px);
    top: 10px;
    color: #ffffff;
  }
  .header-logo {
    float: left;
    width: 180px;
src/tabviews/custom/components/card/cardcellList/index.jsx
@@ -1235,6 +1235,7 @@
            name={name}
            BID={data.$$BID}
            LID={lid}
            columns={cards.columns}
            BData={data.$$BData || ''}
            disabled={_disabled}
            selectedData={_data}
@@ -1297,6 +1298,7 @@
              disabled={_disabled}
              LID={lid}
              btn={card}
              columns={cards.columns}
              selectedData={_data}
            />
          }
src/tabviews/zshare/actionList/funcbutton/index.jsx
@@ -2,9 +2,11 @@
import PropTypes from 'prop-types'
import { is, fromJS } from 'immutable'
import { Button, notification, message, Modal } from 'antd'
import moment from 'moment'
import md5 from 'md5'
import Api from '@/api'
import Utils from '@/utils/utils.js'
import MKEmitter from '@/utils/events.js'
import MkIcon from '@/components/mk-icon'
@@ -165,21 +167,207 @@
        okText: dict['ok'] || '确定',
        cancelText: dict['cancel'] || '取消',
        onOk() {
          that.execRefund(orderId)
          that.execRefund(orderId, data[0])
        },
        onCancel() {}
      })
    }
  }
  execRefund = (orderId) => {
    Api.setRefund(orderId).then(res => {
      if (!res.status) {
        this.execError({ErrCode: 'E', message: window.GLOB.dict['exc_fail'] || '执行失败!', ...res})
      } else {
        this.execSuccess({ErrCode: 'S', ...res})
  execRefund = (orderId, data) => {
    const { btn, BID } = this.props
    let param = null
    if (btn.payMode === 'inner') {
      param = {
        func: btn.innerFunc || '',
        BID: BID || '',
        username: sessionStorage.getItem('User_Name') || '',
        fullname: sessionStorage.getItem('Full_Name') || '',
        dataM: sessionStorage.getItem('dataM') === 'true' ? 'Y' : '',
        ID: orderId
      }
    } else if (btn.payMode === 'system') {
      let sql = this.getSysDeclareSql(orderId, data)
      param = {
        func: 'sPC_TableData_InUpDe',
        BID: BID || '',
        exec_type: window.GLOB.execType || 'y',
        timestamp: moment().format('YYYY-MM-DD HH:mm:ss')
      }
      param.secretkey = Utils.encrypt('', param.timestamp)
      param.LText = Utils.formatOptions(sql, param.exec_type)
      if (btn.output) {
        param.key_back_type = 'Y'
      }
      if (window.GLOB.mkHS) { // 函数 sPC_TableData_InUpDe 云端验证
        param.open_key = Utils.encryptOpenKey(param.secretkey, param.timestamp)
      }
      param.menuname = btn.logLabel
      if (window.GLOB.probation) {
        param.s_debug_type = 'Y'
      }
    }
    let appId = window.GLOB.WXAppID || window.GLOB.WXminiAppID || ''
    if (btn.wxApp && window.GLOB.WXApps && window.GLOB.WXApps.findIndex(item => item.appId === btn.wxApp) > -1) {
      appId = btn.wxApp
    }
    if (!appId) {
      notification.warning({
        top: 10,
        message: '未获取到应用ID!',
        duration: 5
      })
      return
    }
    this.setState({loading: true})
    if (param) {
      Api.genericInterface(param).then(res => {
        if (res.status) {
          let id = orderId
          if (btn.output) {
            id = res.mk_b_id || res[btn.output] || orderId
          }
          Api.setRefund({out_biz_no: id, app_id: appId}).then(res => {
            if (!res.status) {
              this.execError({ErrCode: 'E', message: res.message || window.GLOB.dict['exc_fail'] || '执行失败!', ...res})
            } else {
              this.execSuccess({ErrCode: 'S', ...res})
            }
          })
        } else {
          this.execError(res)
        }
      })
    } else {
      Api.setRefund({out_biz_no: orderId, app_id: appId}).then(res => {
        if (!res.status) {
          this.execError({ErrCode: 'E', message: res.message || window.GLOB.dict['exc_fail'] || '执行失败!', ...res})
        } else {
          this.execSuccess({ErrCode: 'S', ...res})
        }
      })
    }
  }
  getSysDeclareSql = (ID, data) => {
    const { columns, btn, BID } = this.props
    // 系统变量
    let _vars = ['tbid', 'errorcode', 'retmsg', 'username', 'fullname', 'roleid', 'mk_departmentcode', 'mk_organization', 'mk_user_type', 'mk_nation', 'mk_province', 'mk_city', 'mk_district', 'mk_address', 'bid']
    let _declare = []
    let _initVal = []
    let _data = {}
    Object.keys(data).forEach(key => {
      _data[key.toLowerCase()] = data[key]
    })
    columns.forEach(col => {
      let _key = col.field.toLowerCase()
      if (_vars.includes(_key)) return
      _declare.push(`@${_key} ${col.datatype}`)
      let _val = _data.hasOwnProperty(_key) ? _data[_key] : ''
      if (/^date/ig.test(col.datatype) && !_val) {
        _val = '1949-10-01'
      }
      if (/'/.test(_val)) {
        _val = _val.replace(/'/ig, '"')
      }
      _initVal.push(`@${_key}='${_val}'`)
    })
    // 变量声明
    _declare = _declare.join(',')
    if (_declare) {
      _declare = ',' + _declare
    }
    let _sql = `/* 系统生成 */
      Declare @ErrorCode nvarchar(50),@retmsg nvarchar(4000), @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),@bid nvarchar(50),@tbid nvarchar(50)${_declare}
    `
    let userName = sessionStorage.getItem('User_Name') || ''
    let fullName = sessionStorage.getItem('Full_Name') || ''
    let RoleID = sessionStorage.getItem('role_id') || ''
    let departmentcode = sessionStorage.getItem('departmentcode') || ''
    let organization = sessionStorage.getItem('organization') || ''
    let mk_user_type = sessionStorage.getItem('mk_user_type') || ''
    let nation = sessionStorage.getItem('nation') || ''
    let province = sessionStorage.getItem('province') || ''
    let city = sessionStorage.getItem('city') || ''
    let district = sessionStorage.getItem('district') || ''
    let address = sessionStorage.getItem('address') || ''
    // 初始化凭证及用户信息字段
    _sql += `
      /* 用户信息初始化赋值 */
      select @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}', @bid='${BID}'
    `
    _sql += `
      /* 显示列变量赋值 */
      select ${_initVal.join(',')}
    `
    btn.verify.scripts.forEach(item => {
      if (item.status === 'false') return
      _sql += `
      ${item.sql}
      `
    })
    if (btn.output) {
      _sql += `
        aaa: select @ErrorCode as ErrorCode,@retmsg as retmsg,${btn.output} as mk_b_id`
    } else {
      _sql += `
        aaa: select @ErrorCode as ErrorCode,@retmsg as retmsg`
    }
    _sql = _sql.replace(/@ID@/ig, `'${ID || ''}'`)
    _sql = _sql.replace(/@BID@/ig, `'${BID || ''}'`)
    _sql = _sql.replace(/@LoginUID@/ig, `'${sessionStorage.getItem('LoginUID') || ''}'`)
    _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 (window.GLOB.externalDatabase !== null) {
      _sql = _sql.replace(/@db@/ig, window.GLOB.externalDatabase)
    }
    if (sessionStorage.getItem('dataM') === 'true') { // 数据权限
      _sql = _sql.replace(/\$@/ig, '/*').replace(/@\$/ig, '*/').replace(/@datam@/ig, `'Y'`)
    } else {
      _sql = _sql.replace(/@\$|\$@/ig, '').replace(/@datam@/ig, `''`)
    }
    if (window.GLOB.debugger === true) {
      console.info('%c' + btn.logLabel, 'color: blue')
      console.info(_sql)
    }
    return _sql
  }
  getShortUrl = (url) => {
src/tabviews/zshare/actionList/index.jsx
@@ -134,6 +134,7 @@
            BID={BID}
            btn={item}
            BData={BData}
            columns={columns}
            selectedData={selectedData}
          />
        )
@@ -213,6 +214,7 @@
              key={item.uuid}
              BID={BID}
              btn={item}
              columns={columns}
              selectedData={selectedData}
            />
          )
src/tabviews/zshare/actionList/newpagebutton/index.jsx
@@ -1,8 +1,11 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import { is, fromJS } from 'immutable'
import { Button, notification, Modal } from 'antd'
import { Button, notification, Modal, message } from 'antd'
import moment from 'moment'
import Api from '@/api'
import Utils from '@/utils/utils.js'
import MKEmitter from '@/utils/events.js'
import MkIcon from '@/components/mk-icon'
import './index.scss'
@@ -21,8 +24,10 @@
  state = {
    disabled: false,
    loading: false,
    hidden: false,
    visible: false
    visible: false,
    dict: window.GLOB.dict
  }
  UNSAFE_componentWillMount () {
@@ -102,7 +107,7 @@
   */
  actionTrigger = (triggerId, record, type, lid) => {
    const { btn, selectedData, BID, LID } = this.props
    const { disabled } = this.state
    const { disabled, dict } = this.state
    if (disabled) return
    if (triggerId && btn.uuid !== triggerId) return
@@ -114,7 +119,7 @@
      // 需要选择行时,校验数据
      notification.warning({
        top: 92,
        message: window.GLOB.dict['select_row'] || '请选择行!',
        message: dict['select_row'] || '请选择行!',
        duration: 5
      })
      return
@@ -122,14 +127,14 @@
      // 需要选择单行时,校验数据
      notification.warning({
        top: 92,
        message: window.GLOB.dict['select_single_row'] || '请选择单行数据!',
        message: dict['select_single_row'] || '请选择单行数据!',
        duration: 5
      })
      return
    } else if (btn.pageTemplate === 'custom' && window.GLOB.systemType === 'production' && !btn.proUrl) {
      notification.warning({
        top: 92,
        message: window.GLOB.dict['no_prod_link'] || '尚未设置正式系统链接地址!',
        message: dict['no_prod_link'] || '尚未设置正式系统链接地址!',
        duration: 5
      })
      return
@@ -234,25 +239,34 @@
      let src = '#/print/' + window.btoa(window.encodeURIComponent(JSON.stringify({ ID: Id, lang })))
      window.open(src)
    } else if (btn.pageTemplate === 'pay') {
      let _p = `ID=${Id}&userid=${sessionStorage.getItem('UserID')}&LoginUID=${sessionStorage.getItem('LoginUID')}&logo=${window.GLOB.doclogo}&name=${sessionStorage.getItem('Full_Name')}&icp=${window.GLOB.ICP}&copyRight=${window.GLOB.copyRight}`
      let url = '#/pay/' +  window.btoa(window.encodeURIComponent(_p))
      _name = '支付'
      confirm({
        title: '请在付款页面完成订单支付。',
        content: '',
        className: 'pay-query',
        okText: '支付成功',
        cancelText: '支付遇到问题',
        onOk() {
          // 支付后刷新界面
          MKEmitter.emit('reloadMenuView', btn.$MenuID)
        },
        onCancel() {
          MKEmitter.emit('refreshByButtonResult', btn.$menuId, 'grid', btn)
        },
      })
      window.open(url)
      if (btn.payMode === 'system' || btn.payMode === 'inner') {
        this.prequest(Id, data[0] || {})
      } else {
        confirm({
          title: '请在付款页面完成订单支付。',
          content: '',
          className: 'pay-query',
          okText: '支付成功',
          cancelText: '支付遇到问题',
          onOk() {
            // 支付后刷新界面
            MKEmitter.emit('reloadMenuView', btn.$MenuID)
          },
          onCancel() {
            MKEmitter.emit('refreshByButtonResult', btn.$menuId, 'grid', btn)
          },
        })
        let appId = ''
        if (btn.wxApp && window.GLOB.WXApps && window.GLOB.WXApps.findIndex(item => item.appId === btn.wxApp) > -1) {
          appId = btn.wxApp
        }
        window.open('#/pay/' + window.btoa(window.encodeURIComponent(JSON.stringify({ ID: Id, appId: appId }))))
      }
    } else if (btn.pageTemplate === 'custom') {
      let url = btn.url
      if (window.GLOB.systemType === 'production') {
@@ -309,9 +323,226 @@
    }
  }
  prequest = (ID, data) => {
    const { btn, BID } = this.props
    let param = null
    if (btn.payMode === 'inner') {
      param = {
        func: btn.innerFunc || '',
        BID: BID || '',
        username: sessionStorage.getItem('User_Name') || '',
        fullname: sessionStorage.getItem('Full_Name') || '',
        dataM: sessionStorage.getItem('dataM') === 'true' ? 'Y' : '',
        ID: ID
      }
    } else {
      let sql = this.getSysDeclareSql(ID, data)
      param = {
        func: 'sPC_TableData_InUpDe',
        BID: BID || '',
        exec_type: window.GLOB.execType || 'y',
        timestamp: moment().format('YYYY-MM-DD HH:mm:ss')
      }
      param.secretkey = Utils.encrypt('', param.timestamp)
      param.LText = Utils.formatOptions(sql, param.exec_type)
      if (btn.output) {
        param.key_back_type = 'Y'
      }
      if (window.GLOB.mkHS) { // 函数 sPC_TableData_InUpDe 云端验证
        param.open_key = Utils.encryptOpenKey(param.secretkey, param.timestamp)
      }
      param.menuname = btn.logLabel
      if (window.GLOB.probation) {
        param.s_debug_type = 'Y'
      }
    }
    this.setState({loading: true})
    Api.genericInterface(param).then(res => {
      this.setState({loading: false})
      if (res.status) {
        let id = ID
        if (btn.output) {
          id = res.mk_b_id || res[btn.output] || ID
        }
        confirm({
          title: '请在付款页面完成订单支付。',
          content: '',
          className: 'pay-query',
          okText: '支付成功',
          cancelText: '支付遇到问题',
          onOk() {
            // 支付后刷新界面
            MKEmitter.emit('reloadMenuView', btn.$MenuID)
          },
          onCancel() {
            MKEmitter.emit('refreshByButtonResult', btn.$menuId, 'grid', btn)
          },
        })
        let appId = ''
        if (btn.wxApp && window.GLOB.WXApps && window.GLOB.WXApps.findIndex(item => item.appId === btn.wxApp) > -1) {
          appId = btn.wxApp
        }
        window.open('#/pay/' + window.btoa(window.encodeURIComponent(JSON.stringify({ ID: id, appId: appId }))))
      } else {
        this.execError(res)
      }
    })
  }
  getSysDeclareSql = (ID, data) => {
    const { columns, btn, BID } = this.props
    // 系统变量
    let _vars = ['tbid', 'errorcode', 'retmsg', 'username', 'fullname', 'roleid', 'mk_departmentcode', 'mk_organization', 'mk_user_type', 'mk_nation', 'mk_province', 'mk_city', 'mk_district', 'mk_address', 'bid']
    let _declare = []
    let _initVal = []
    let _data = {}
    Object.keys(data).forEach(key => {
      _data[key.toLowerCase()] = data[key]
    })
    columns.forEach(col => {
      let _key = col.field.toLowerCase()
      if (_vars.includes(_key)) return
      _declare.push(`@${_key} ${col.datatype}`)
      let _val = _data.hasOwnProperty(_key) ? _data[_key] : ''
      if (/^date/ig.test(col.datatype) && !_val) {
        _val = '1949-10-01'
      }
      if (/'/.test(_val)) {
        _val = _val.replace(/'/ig, '"')
      }
      _initVal.push(`@${_key}='${_val}'`)
    })
    // 变量声明
    _declare = _declare.join(',')
    if (_declare) {
      _declare = ',' + _declare
    }
    let _sql = `/* 系统生成 */
      Declare @ErrorCode nvarchar(50),@retmsg nvarchar(4000), @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),@bid nvarchar(50),@tbid nvarchar(50)${_declare}
    `
    let userName = sessionStorage.getItem('User_Name') || ''
    let fullName = sessionStorage.getItem('Full_Name') || ''
    let RoleID = sessionStorage.getItem('role_id') || ''
    let departmentcode = sessionStorage.getItem('departmentcode') || ''
    let organization = sessionStorage.getItem('organization') || ''
    let mk_user_type = sessionStorage.getItem('mk_user_type') || ''
    let nation = sessionStorage.getItem('nation') || ''
    let province = sessionStorage.getItem('province') || ''
    let city = sessionStorage.getItem('city') || ''
    let district = sessionStorage.getItem('district') || ''
    let address = sessionStorage.getItem('address') || ''
    // 初始化凭证及用户信息字段
    _sql += `
      /* 用户信息初始化赋值 */
      select @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}', @bid='${BID}'
    `
    _sql += `
      /* 显示列变量赋值 */
      select ${_initVal.join(',')}
    `
    btn.verify.scripts.forEach(item => {
      if (item.status === 'false') return
      _sql += `
      ${item.sql}
      `
    })
    if (btn.output) {
      _sql += `
        aaa: select @ErrorCode as ErrorCode,@retmsg as retmsg,${btn.output} as mk_b_id`
    } else {
      _sql += `
        aaa: select @ErrorCode as ErrorCode,@retmsg as retmsg`
    }
    _sql = _sql.replace(/@ID@/ig, `'${ID || ''}'`)
    _sql = _sql.replace(/@BID@/ig, `'${BID || ''}'`)
    _sql = _sql.replace(/@LoginUID@/ig, `'${sessionStorage.getItem('LoginUID') || ''}'`)
    _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 (window.GLOB.externalDatabase !== null) {
      _sql = _sql.replace(/@db@/ig, window.GLOB.externalDatabase)
    }
    if (sessionStorage.getItem('dataM') === 'true') { // 数据权限
      _sql = _sql.replace(/\$@/ig, '/*').replace(/@\$/ig, '*/').replace(/@datam@/ig, `'Y'`)
    } else {
      _sql = _sql.replace(/@\$|\$@/ig, '').replace(/@datam@/ig, `''`)
    }
    if (window.GLOB.debugger === true) {
      console.info('%c' + btn.logLabel, 'color: blue')
      console.info(_sql)
    }
    return _sql
  }
  execError = (res) => {
    const { btn } = this.props
    const { dict } = this.state
    if (!['LoginError', 'C', '-2', 'E', 'N', 'F', 'NM'].includes(res.ErrCode)) {
      res.ErrCode = 'E'
    }
    if (res.ErrCode === 'E') {
      Modal.error({
        title: res.message || dict['exc_fail'] || '执行失败!',
        okText: dict['got_it'] || '知道了'
      })
    } else if (res.ErrCode === 'N') {
      notification.error({
        top: 92,
        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 || dict['exc_fail'] || '执行失败!',
        duration: btn.verify && btn.verify.ftime ? btn.verify.ftime : 10
      })
    } else if (res.ErrCode === 'NM') {
      message.error(res.message || dict['exc_fail'] || '执行失败!')
    }
  }
  render() {
    const { btn, name } = this.props
    const { disabled, hidden } = this.state
    const { disabled, hidden, loading } = this.state
    if (hidden) return null
@@ -331,6 +562,7 @@
        id={'button' + btn.uuid}
        title={disabled ? (btn.reason || '') : (btn.show === 'icon' ? btn.label : '')}
        style={btn.style || null}
        loading={loading}
        disabled={disabled}
        className={btn.hover || ''}
        onClick={(e) => {e.stopPropagation(); this.actionTrigger()}}
src/tabviews/zshare/actionList/normalbutton/index.jsx
@@ -2553,8 +2553,15 @@
  sendWxMessage = (verify, id) => {
    let domain = ''
    let appId = window.GLOB.WXAppID || ''
    if (verify.wxAppId && window.GLOB.WXApps && window.GLOB.WXApps.findIndex(item => item.appId === verify.wxAppId) > -1) {
      appId = verify.wxAppId
    }
    if (['8IFltwzyKcu15iA8fqSyb6m-pMa88a3ZTu0No3vDHgo', 'LOB-bbt9jVncGh7IOAUdESh1Sgzcbt62UwOqSqcK9ok'].includes(verify.wxTemplateId) && window.GLOB.sysType !== 'cloud') {
      domain = 'https://cloud.mk9h.cn/'
      appId = 'wx4d8a34c8d4494872'
    }
    if (!window.GLOB.nginx && !domain) {
@@ -2564,7 +2571,7 @@
        duration: 5
      })
      return
    } else if (!window.GLOB.WXAppID && !domain) {
    } else if (!appId) {
      notification.warning({
        top: 92,
        message: '尚未添加公众号ID,不可发送模板消息。',
@@ -2644,11 +2651,11 @@
        return m
      })
      Api.wxAccessToken(domain).then(res => {
        if (!res.oa_access_token) return
      Api.wxAccessToken(appId, domain).then(res => {
        if (!res.access_token) return
  
        params.forEach(n => {
          Api.wxNginxRequest(`${domain}cgi-bin/message/template/send?access_token=${res.oa_access_token}`, 'post', JSON.stringify(n)).then(re => {
          Api.wxNginxRequest(`${domain}cgi-bin/message/template/send?access_token=${res.access_token}`, 'post', JSON.stringify(n)).then(re => {
            if (verify.wxNoteCallback === 'true') {
              let msg = re.errmsg || ''
src/templates/sharecomponent/actioncomponent/verifypay/customscript/index.jsx
New file
@@ -0,0 +1,224 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import { fromJS } from 'immutable'
import { Form, Row, Col, Button, notification, Tooltip, Select, Switch } from 'antd'
import Utils from '@/utils/utils.js'
import { checkSQL } from '@/utils/utils-custom.js'
import CodeMirror from '@/templates/zshare/codemirror'
// import './index.scss'
class CustomForm extends Component {
  static propTpyes = {
    scripts: PropTypes.array,
    columns: PropTypes.any,
    systemScripts: PropTypes.array,
    scriptsChange: PropTypes.func
  }
  state = {
    editItem: null,
    usefulfields: null,
    loading: false,
    skip: false
  }
  UNSAFE_componentWillMount () {
    this.resetfield()
  }
  resetfield = () => {
    const { columns } = this.props
    let fields = columns.map(item => item.field)
    this.setState({
      usefulfields: fields.join(', ')
    })
  }
  edit = (record) => {
    this.setState({
      editItem: record
    })
    this.props.form.setFieldsValue({
      sql: record.sql
    })
  }
  handleConfirm = () => {
    const { type, scripts } = this.props
    const { editItem, skip } = this.state
    // 表单提交时检查输入值是否正确
    this.props.form.validateFieldsAndScroll((err, values) => {
      if (err) return
      if (!values.sql || /^[\s\n]+$/.test(values.sql)) {
        notification.warning({
          top: 92,
          message: '请输入sql!',
          duration: 5
        })
        return
      }
      values.uuid = editItem ? editItem.uuid : ''
      if (type === 'fullscreen' && editItem) {
        values.status = editItem.status || 'true'
      }
      let pass = checkSQL(values.sql, 'customscript')
      if (!pass) return
      let _scripts = fromJS(scripts).toJS()
      if (values.uuid) {
        _scripts = _scripts.map(item => {
          if (values.uuid === item.uuid) {
            return values
          }
          return item
        })
      } else {
        values.uuid = Utils.getuuid()
        _scripts.push(values)
      }
      if (skip) {
        this.setState({
          skip: false,
          editItem: null
        })
        this.props.scriptsChange(_scripts, null, null, values)
        this.props.form.setFieldsValue({
          sql: ''
        })
      } else {
        this.setState({loading: true})
        this.props.scriptsChange(_scripts, () => {
          this.setState({
            loading: false,
            editItem: null
          })
          this.props.form.setFieldsValue({
            sql: ''
          })
        }, () => {
          this.setState({loading: false})
        }, values)
      }
    })
  }
  handleCancel = () => {
    this.setState({
      editItem: null
    })
    this.props.form.setFieldsValue({
      sql: ''
    })
  }
  selectScript = (value, option) => {
    let _sql = this.props.form.getFieldValue('sql')
    if (/^\s+$/.test(_sql)) {
      _sql = ''
    }
    if (_sql) {
      _sql = _sql + `
      `
    }
    _sql = _sql.replace(/\s{6}$/, '')
    _sql = _sql + `/*${option.props.children}*/
    `
    _sql = _sql.replace(/\s{4}$/, '')
    _sql = _sql + value
    this.props.form.setFieldsValue({
      sql: _sql
    })
  }
  render() {
    const { systemScripts, type } = this.props
    const { usefulfields, editItem, skip } = this.state
    const { getFieldDecorator } = this.props.form
    const formItemLayout = {
      labelCol: {
        xs: { span: 24 },
        sm: { span: 8 }
      },
      wrapperCol: {
        xs: { span: 24 },
        sm: { span: 16 }
      }
    }
    return (
      <Form {...formItemLayout} className="verify-form" id="verify-excelin-custom-scripts">
        <Row gutter={24}>
          {!type ? <Col span={8}>
            <Form.Item label="报错字段" style={{margin: 0, whiteSpace: 'nowrap'}}>
              errorcode(增加后缀NT表示数据不回滚,如ENT、NNT、FNT、NMNT、CNT、-2NT), retmsg
            </Form.Item>
          </Col> : null}
          {!type ? <Col span={24} className="sqlfield">
            <Form.Item label="可用字段">
              <Tooltip mouseLeaveDelay={0.3} mouseEnterDelay={0.3} placement="top" title={'公共值,请按照@xxx@格式使用。'}><span style={{color: '#1890ff'}}>BID, ID, LoginUID, SessionUid, UserID, Appkey, lang, time_id, typename</span></Tooltip>,&nbsp;
              <Tooltip mouseLeaveDelay={0.3} mouseEnterDelay={0.3} placement="top" title={'系统变量,系统会定义变量并赋值。'}><span style={{color: '#fa8c16'}}>UserName, FullName, RoleID, mk_departmentcode, mk_organization, mk_user_type, mk_nation, mk_province, mk_city, mk_district, mk_address</span></Tooltip>,&nbsp;
              {usefulfields}
            </Form.Item>
          </Col> : null}
          {!type ? <Col span={8}>
            <Form.Item style={{marginBottom: 0}} label="快捷添加">
              <Select
                showSearch
                filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0}
                onSelect={this.selectScript}
                getPopupContainer={() => document.getElementById('verify-excelin-custom-scripts')}
              >
                <Select.Option key="debugger" value={`z_debug: select @ErrorCode='E',@retmsg='测试断点' goto aaa`}>
                  测试断点
                </Select.Option>
                {systemScripts.map((option, i) =>
                  <Select.Option key={i} value={option.value}>
                    {option.name}
                  </Select.Option>
                )}
              </Select>
            </Form.Item>
          </Col> : null}
          <Col span={5} className="add" style={{paddingTop: '2px', whiteSpace: 'nowrap'}}>
            <Button onClick={this.handleConfirm} loading={this.state.loading} className="mk-green" style={{marginBottom: 15, marginLeft: 40}}>
            {type === 'fullscreen' && !editItem ? '添加' : '保存'}
            </Button>
            <Button onClick={this.handleCancel} style={{marginBottom: 15, marginLeft: 10}}>
              取消
            </Button>
          </Col>
          <Col span={3} className="forced" style={{paddingTop: '12px', fontSize: '12px', whiteSpace: 'nowrap'}}>
            强制保存:
            <Switch checked={skip} size="small" onChange={() => this.setState({skip: !skip})}/>
          </Col>
          <Col span={24} className="sql">
            <Form.Item label="sql" required>
              {getFieldDecorator('sql', {
                initialValue: ''
              })(<CodeMirror />)}
            </Form.Item>
          </Col>
        </Row>
      </Form>
    )
  }
}
export default Form.create()(CustomForm)
src/templates/sharecomponent/actioncomponent/verifypay/customscript/index.scss
src/templates/sharecomponent/actioncomponent/verifypay/index.jsx
New file
@@ -0,0 +1,516 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import { is, fromJS } from 'immutable'
import { Form, Tabs, Row, Col, Button, Popconfirm, notification, Modal, message, InputNumber, Typography } from 'antd'
import { EditOutlined, StopOutlined, CheckCircleOutlined, SwapOutlined, DeleteOutlined } from '@ant-design/icons'
import moment from 'moment'
import Api from '@/api'
import Utils from '@/utils/utils.js'
import CustomScript from './customscript'
import asyncComponent from '@/utils/asyncComponent'
import MKEmitter from '@/utils/events.js'
import './index.scss'
const { TabPane } = Tabs
const { confirm } = Modal
const { Paragraph } = Typography
const EditTable = asyncComponent(() => import('@/templates/zshare/editTable'))
const FullScripts = asyncComponent(() => import('@/templates/zshare/verifycard/fullScripts'))
class VerifyPay extends Component {
  static propTpyes = {
    columns: PropTypes.array,  // 显示列
    card: PropTypes.object,
  }
  state = {
    verify: null,
    oriVerify: null,
    defaultSql: '',
    systemScripts: [],
    scriptsColumns: [
      {
        title: 'SQL',
        dataIndex: 'sql',
        width: '60%',
        render: (text) => {
          let title = text.match(/^\s*\/\*.+\*\//)
          title = title && title[0] ? title[0] : ''
          let _text = title ? text.replace(title, '') : text
          return (
            <div>
              {title ? <span style={{color: '#a50'}}>{title}<span style={{fontSize: '12px', marginLeft: '5px'}}>{_text.length}</span></span> : null}
              <Paragraph copyable={{ text: text }} ellipsis={{ rows: 4, expandable: true }}>{_text}</Paragraph>
            </div>
          )
        }
      },
      {
        title: '状态',
        dataIndex: 'status',
        width: '10%',
        render: (text, record) => record.status === 'false' ?
          (
            <div style={{color: '#ff4d4f'}}>
              禁用
              <StopOutlined style={{marginLeft: '5px'}} />
            </div>
          ) :
          (
            <div style={{color: '#26C281'}}>
              启用
              <CheckCircleOutlined style={{marginLeft: '5px'}}/>
            </div>
          )
      },
      {
        title: '操作',
        align: 'center',
        width: '140px',
        dataIndex: 'operation',
        render: (text, record) =>
          (<div style={{textAlign: 'center'}}>
            <span className="operation-btn" title="编辑" onClick={() => this.handleEdit(record)} style={{color: '#1890ff'}}><EditOutlined /></span>
            <span className="operation-btn" title="状态切换" onClick={() => this.handleStatus(record)} style={{color: '#8E44AD'}}><SwapOutlined /></span>
            <Popconfirm
              overlayClassName="popover-confirm"
              title="确定删除吗?"
              onConfirm={() => this.handleDelete(record)
            }>
              <span className="operation-btn" style={{color: '#ff4d4f'}}><DeleteOutlined /></span>
            </Popconfirm>
          </div>)
      }
    ]
  }
  UNSAFE_componentWillMount() {
    const { card, columns } = this.props
    let _verify = fromJS(card.verify || {}).toJS()
    _verify.scripts = _verify.scripts || []
    let sysfields = ['UserName', 'FullName', 'RoleID', 'mk_departmentcode', 'mk_organization', 'mk_user_type', 'mk_nation', 'mk_province', 'mk_city', 'mk_district', 'mk_address', 'tbid', 'bid']
    let _declare = ['@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)', '@ErrorCode nvarchar(50)', '@retmsg nvarchar(4000)', '@bid nvarchar(50)', '@tbid nvarchar(50)']
    let _select = ['@UserName=\'\'', '@FullName=\'\'', '@RoleID=\'\'', '@mk_departmentcode=\'\'', '@mk_organization=\'\'', '@mk_user_type=\'\'', '@mk_nation=\'\'', '@mk_province=\'\'', '@mk_city=\'\'', '@mk_district=\'\'', '@mk_address=\'\'', '@ErrorCode=\'\'', '@retmsg=\'\'', '@bid=\'\'']
    sysfields = sysfields.map(field => field.toLowerCase())
    columns.forEach(_f => {
      if (sysfields.includes(_f.field.toLowerCase())) return
      if (/decimal|int/ig.test(_f.datatype)) {
        _select.push(`@${_f.field}=1`)
      } else if (/date/ig.test(_f.datatype)) {
        _select.push(`@${_f.field}='1949-10-01'`)
      } else {
        _select.push(`@${_f.field}=''`)
      }
      _declare.push(`@${_f.field} ${_f.datatype}`)
    })
    let _sql = `Declare ${_declare.join(', ')}
      Select ${_select.join(', ')}
    `
    this.setState({
      defaultSql: _sql,
      verify: _verify,
      oriVerify: fromJS(_verify).toJS()
    })
  }
  componentDidMount () {
    this.getsysScript()
  }
  getsysScript = () => {
    if (sessionStorage.getItem('mk_sys_scripts')) {
      this.setState({
        systemScripts: JSON.parse(sessionStorage.getItem('mk_sys_scripts'))
      })
      return
    }
    let _scriptSql = `Select distinct func+Remark as funcname,longparam, s.Sort from  s_custom_script s inner join (select OpenID from sapp where ID=@Appkey@) p on s.openid = case when s.appkey='' then s.openid else p.OpenID end order by s.Sort`
    _scriptSql = Utils.formatOptions(_scriptSql, 'x')
    let _sParam = {
      func: 'sPC_Get_SelectedList',
      LText: _scriptSql,
      obj_name: 'data',
      arr_field: 'funcname,longparam',
      exec_type: 'x'
    }
    _sParam.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
    _sParam.secretkey = Utils.encrypt('', _sParam.timestamp)
    _sParam.open_key = Utils.encryptOpenKey(_sParam.secretkey, _sParam.timestamp) // 云端数据验证
    Api.getCloudConfig(_sParam).then(res => {
      if (res.status) {
        let _scripts = res.data.map(item => {
          return {
            name: item.funcname,
            value: window.decodeURIComponent(window.atob(item.longparam))
          }
        })
        sessionStorage.setItem('mk_sys_scripts', JSON.stringify(_scripts))
        this.setState({
          systemScripts: _scripts
        })
      } else {
        notification.warning({
          top: 92,
          message: res.message,
          duration: 5
        })
      }
    })
  }
  scriptsChange = (scripts, resolve, reject, values) => {
    const { card } = this.props
    const { defaultSql } = this.state
    let verify = fromJS(this.state.verify).toJS()
    verify.scripts = scripts
    let sql = defaultSql
    scripts.forEach(item => {
      if (item.status === 'false') return
      sql += `
      ${item.sql}
      `
    })
    if (card.output) {
      sql += `
        aaa: select @ErrorCode as ErrorCode,@retmsg as retmsg,${card.output} as mk_b_id`
    } else {
      sql += `
        aaa: select @ErrorCode as ErrorCode,@retmsg as retmsg`
    }
    sql = sql.replace(/@\$|\$@/ig, '')
    sql = sql.replace(/@datam@/ig, `''`)
    sql = sql.replace(/@typename@/ig, `'debug'`)
    if (resolve) {
      Api.sDebug(sql).then(res => {
        if (res.status || res.ErrCode === '-2') {
          resolve()
          values && MKEmitter.emit('editLineId', values.uuid)
          this.setState({ verify })
        } else {
          reject()
          Modal.error({
            title: res.message
          })
        }
      })
    } else {
      values && MKEmitter.emit('editLineId', values.uuid)
      this.setState({ verify })
    }
  }
  handleDelete = (record) => {
    const { verify } = this.state
    verify.scripts = verify.scripts.filter(item => item.uuid !== record.uuid)
    this.setState({ verify: verify })
  }
  handleEdit = (record) => {
    this.scriptsForm.edit(record)
    let node = document.getElementById('mk-pay-script')
    if (node && node.scrollTop) {
      let inter = Math.ceil(node.scrollTop / 10)
      let timer = setInterval(() => {
        if (node.scrollTop - inter > 0) {
          node.scrollTop = node.scrollTop - inter
        } else {
          node.scrollTop = 0
          clearInterval(timer)
        }
      }, 10)
    }
  }
  handleStatus = (record) => {
    let verify = fromJS(this.state.verify).toJS()
    record.status = record.status === 'false' ? 'true' : 'false'
    verify.scripts = verify.scripts.map(item => {
      if (item.uuid === record.uuid) {
        return record
      } else {
        return item
      }
    })
    this.setState({
      verify: verify
    })
  }
  handleConfirm = () => {
    const { verify } = this.state
    // 表单提交时检查输入值是否正确
    return new Promise((resolve, reject) => {
      if (verify.scripts.length === 0) {
        notification.warning({
          top: 92,
          message: '使用系统函数,需要添加自定义脚本!',
          duration: 5
        })
        return
      }
      let _loading = false
      if (this.scriptsForm && this.scriptsForm.state.editItem) {
        _loading = true
      } else if (this.scriptsForm && this.scriptsForm.props.form.getFieldValue('sql') && !/^\s+$/.test(this.scriptsForm.props.form.getFieldValue('sql'))) {
        _loading = true
      }
      if (_loading) {
        confirm({
          content: `存在未保存项,确定提交吗?`,
          onOk() {
            resolve(verify)
          },
          onCancel() {}
        })
      } else {
        resolve(verify)
      }
    })
  }
  handleCancel = () => {
    const { verify, oriVerify } = this.state
    // 表单提交时检查输入值是否正确
    return new Promise((resolve, reject) => {
      if (!is(fromJS(verify), fromJS(oriVerify))) {
        confirm({
          content: '验证信息已修改,确定取消吗?',
          onOk() {
            resolve()
          },
          onCancel() {}
        })
      } else {
        resolve()
      }
    })
  }
  showError = (errorType) => {
    if (errorType === 'S') {
      notification.success({
        top: 92,
        message: '执行成功!',
        duration: 2
      })
    } else if (errorType === 'Y') {
      Modal.success({
        title: '执行成功!'
      })
    } else if (errorType === 'F') {
      notification.error({
        className: 'notification-custom-error',
        top: 92,
        message: '执行失败!',
        duration: 10
      })
    } else if (errorType === 'N') {
      notification.error({
        top: 92,
        message: '执行失败!',
        duration: 10
      })
    } else if (errorType === 'E') {
      Modal.error({
        title: '执行失败!'
      })
    } else if (errorType === 'NM') {
      message.error('执行失败!')
    }
  }
  timeChange = (val, type) => {
    const { verify } = this.state
    this.setState({
      verify: {...verify, [type]: val}
    })
  }
  render() {
    const { card, columns } = this.props
    const { verify, scriptsColumns } = this.state
    const formItemLayout = {
      labelCol: {
        xs: { span: 24 },
        sm: { span: 8 }
      },
      wrapperCol: {
        xs: { span: 24 },
        sm: { span: 16 }
      }
    }
    return (
      <div>
        {card.label ? <div className="mk-com-name">{card.label} - 验证信息</div> : null}
        <Tabs className="pay-verify-card-box">
          <TabPane tab={
            <span>
              自定义脚本
              {verify.scripts.length ? <span className="count-tip">{verify.scripts.length}</span> : null}
            </span>
          } key="scripts" id="mk-pay-script">
            <FullScripts
              scripts={verify.scripts}
              getScriptsFullForm={() => this.scriptsFullForm}
              getScriptsForm={() => this.scriptsForm}
              handleStatus={this.handleStatus}
              handleDelete={this.handleDelete}
            >
              <CustomScript
                type="fullscreen"
                columns={columns}
                scripts={verify.scripts}
                systemScripts={this.state.systemScripts}
                scriptsChange={this.scriptsChange}
                wrappedComponentRef={(inst) => this.scriptsFullForm = inst}
              />
            </FullScripts>
            <CustomScript
              columns={columns}
              scripts={verify.scripts}
              systemScripts={this.state.systemScripts}
              scriptsChange={this.scriptsChange}
              wrappedComponentRef={(inst) => this.scriptsForm = inst}
            />
            <EditTable actions={['move']} data={verify.scripts} columns={scriptsColumns} onChange={(scripts) => {this.setState({verify: {...verify, scripts}})}}/>
          </TabPane>
          <TabPane tab="信息提示" key="tip">
            <Form {...formItemLayout}>
              <Row gutter={24}>
                <Col offset={6} span={6}>
                  <Form.Item label="提示编码">
                    <span className="errorval"> S </span>
                    <Button onClick={() => {this.showError('S')}} type="primary" size="small">
                      查看
                    </Button>
                  </Form.Item>
                </Col>
                <Col span={8}>
                  <Form.Item label="停留时间">
                    <InputNumber defaultValue={verify.stime || 2} min={1} max={10000} precision={0} onChange={(val) => {this.timeChange(val, 'stime')}} />
                  </Form.Item>
                </Col>
              </Row>
              <Row gutter={24}>
                <Col offset={6} span={6}>
                  <Form.Item label="提示编码">
                    <span className="errorval"> Y </span>
                    <Button onClick={() => {this.showError('Y')}} type="primary" size="small">
                      查看
                    </Button>
                  </Form.Item>
                </Col>
              </Row>
              <Row gutter={24}>
                <Col offset={6} span={6}>
                  <Form.Item label="提示编码">
                    <span className="errorval"> -1 </span>
                    执行成功无提示。
                  </Form.Item>
                </Col>
              </Row>
              <Row gutter={24}>
                <Col offset={6} span={6}>
                  <Form.Item label="提示编码">
                    <span className="errorval"> N </span>
                    <Button onClick={() => {this.showError('N')}} type="primary" size="small">
                      查看
                    </Button>
                  </Form.Item>
                </Col>
                <Col span={8}>
                  <Form.Item label="停留时间">
                    <InputNumber defaultValue={verify.ntime || 10} min={1} max={10000} precision={0} onChange={(val) => {this.timeChange(val, 'ntime')}} />
                  </Form.Item>
                </Col>
              </Row>
              <Row gutter={24}>
                <Col offset={6} span={6}>
                  <Form.Item label="提示编码">
                    <span className="errorval"> F </span>
                    <Button onClick={() => {this.showError('F')}} type="primary" size="small">
                      查看
                    </Button>
                  </Form.Item>
                </Col>
                <Col span={8}>
                  <Form.Item label="停留时间">
                    <InputNumber defaultValue={verify.ftime || 10} min={1} max={10000} precision={0} onChange={(val) => {this.timeChange(val, 'ftime')}} />
                  </Form.Item>
                </Col>
              </Row>
              <Row gutter={24}>
                <Col offset={6} span={6}>
                  <Form.Item label="提示编码">
                    <span className="errorval"> E </span>
                    <Button onClick={() => {this.showError('E')}} type="primary" size="small">
                      查看
                    </Button>
                  </Form.Item>
                </Col>
              </Row>
              <Row gutter={24}>
                <Col offset={6} span={6}>
                  <Form.Item label="提示编码">
                    <span className="errorval"> NM </span>
                    <Button onClick={() => {this.showError('NM')}} type="primary" size="small">
                      查看
                    </Button>
                  </Form.Item>
                </Col>
              </Row>
              <Row gutter={24}>
                <Col offset={6} span={6}>
                  <Form.Item label="提示编码">
                    <span className="errorval"> -2 </span>
                    执行失败无提示
                  </Form.Item>
                </Col>
              </Row>
            </Form>
          </TabPane>
        </Tabs>
      </div>
    )
  }
}
export default Form.create()(VerifyPay)
src/templates/sharecomponent/actioncomponent/verifypay/index.scss
New file
@@ -0,0 +1,84 @@
.pay-verify-card-box {
  .ant-tabs-nav-scroll {
    text-align: center;
  }
  .ant-tabs-content {
    min-height: 40vh;
  }
  table tr td {
    word-wrap: break-word;
    word-break: break-word;
  }
  .count-tip {
    position: absolute;
    top: 0px;
    color: #1890ff;
    font-size: 12px;
  }
  .verify-form {
    .sql {
      .ant-col-sm-8 {
        width: 10.5%;
      }
      .ant-col-sm-16 {
        width: 89.5%;
        padding-top: 4px;
      }
      .CodeMirror {
        height: 350px;
      }
    }
    .sqlfield {
      .ant-form-item {
        margin-bottom: 5px;
      }
      .ant-form-item-control {
        line-height: 24px;
      }
      .ant-form-item-label {
        line-height: 25px;
      }
      .ant-form-item-children {
        line-height: 22px;
      }
      .ant-col-sm-8 {
        width: 10.5%;
      }
      .ant-col-sm-16 {
        width: 89.5%;
      }
    }
    .ant-form-explain {
      white-space: nowrap;
    }
  }
  .errorval {
    display: inline-block;
    width: 30px;
  }
  .operation-btn {
    display: inline-block;
    font-size: 16px;
    padding: 0 5px;
    cursor: pointer;
  }
  .ant-tabs-tabpane {
    position: relative;
    .excel-col-add {
      position: relative;
      float: right;
      right: -9px;
      margin-right: 10px;
      top: 10px;
      z-index: 1;
    }
  }
  .full-scripts {
    position: absolute;
    right: 24px;
    top: 0px;
    font-size: 16px;
    color: #1890ff;
    z-index: 1;
  }
}
src/templates/sharecomponent/actioncomponent/verifyprint/index.jsx
@@ -247,6 +247,8 @@
        if (/decimal|int/ig.test(_f.datatype)) {
          _select.push(`@${_f.field}=1`)
        } else if (/date/ig.test(_f.datatype)) {
          _select.push(`@${_f.field}='1949-10-01'`)
        } else {
          _select.push(`@${_f.field}=''`)
        }
src/templates/sharecomponent/searchcomponent/searchform/index.jsx
@@ -692,7 +692,7 @@
      fields.push(
        <Col span={span} key={index}>
          <Form.Item className={className} extra={extra} label={item.tooltip ?
            <Tooltip placement="topLeft" title={item.tooltip}>
            <Tooltip placement="topLeft" title={<div onClick={(e) => e.stopPropagation()}>{item.tooltip}</div>}>
              <QuestionCircleOutlined className="mk-form-tip" />
              {item.label}
            </Tooltip> : item.label
src/templates/zshare/verifycard/baseform/index.jsx
@@ -1,7 +1,7 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import { fromJS } from 'immutable'
import { Form, Row, Col, Select, Radio, Tooltip, Input } from 'antd'
import { Form, Row, Col, Select, Radio, Tooltip, Input, message } from 'antd'
import { QuestionCircleOutlined } from '@ant-design/icons'
import Api from '@/api'
@@ -25,42 +25,30 @@
  state = {
    wxTemps: [],
    selectTemp: null,
    miniTemps: []
    WXApps: null
  }
  componentDidMount() {
    let wxTemps = sessionStorage.getItem('wxTemplates')
    const { appType, verify } = this.props
    if (window.GLOB.WXAppID && window.GLOB.nginx && !wxTemps) {
      Api.wxAccessToken().then(res => {
        if (res.access_token) {
          Api.wxNginxRequest(`cgi-bin/template/get_all_private_template?access_token=${res.access_token}`, 'get').then(res => {
            let temps = []
            if (res.template_list) {
              temps = res.template_list.filter(item => {
                if (!item.primary_industry || sysTempsIds.includes(item.template_id)) return false
                if (item.content) {
                  item.content = item.content.replace('{{first.DATA}}\n', '').replace('\n{{remark.DATA}}', '')
                }
    let appId = window.GLOB.WXAppID || ''
                return true
              })
            }
            sessionStorage.setItem('wxTemplates', JSON.stringify(temps))
            localStorage.setItem('wxTemplates', JSON.stringify(temps))
    if (window.GLOB.WXApps && !appType) {
      let apps = window.GLOB.WXApps.filter(app => app.appType === 'public')
            localStorage.removeItem('wxTemplates')
      if (apps.length > 0) {
        this.setState({WXApps: apps})
      }
            this.resetTemps(temps)
          })
        } else {
          sessionStorage.setItem('wxTemplates', JSON.stringify([]))
          localStorage.setItem('wxTemplates', JSON.stringify([]))
      if (verify.wxAppId && apps.findIndex(item => item.appId === verify.wxAppId) > -1) {
        appId = verify.wxAppId
      }
    }
          localStorage.removeItem('wxTemplates')
        }
      })
    let wxTemps = sessionStorage.getItem('wxTemplates' + appId)
    if (appId && window.GLOB.nginx && !wxTemps) {
      this.getTemps(appId)
    } else if (wxTemps) {
      wxTemps = JSON.parse(wxTemps)
@@ -68,6 +56,35 @@
    } else {
      this.resetTemps([])
    }
  }
  getTemps = (appId) => {
    Api.wxAccessToken(appId).then(res => {
      if (res.status && res.access_token) {
        Api.wxNginxRequest(`cgi-bin/template/get_all_private_template?access_token=${res.access_token}`, 'get').then(res => {
          let temps = []
          if (res.template_list) {
            temps = res.template_list.filter(item => {
              if (!item.primary_industry || sysTempsIds.includes(item.template_id)) return false
              if (item.content) {
                item.content = item.content.replace('{{first.DATA}}\n', '').replace('\n{{remark.DATA}}', '')
              }
              return true
            })
          } else if (res.errcode && res.errmsg) {
            message.warning(res.errcode + ': ' + res.errmsg)
          }
          sessionStorage.setItem('wxTemplates' + appId, JSON.stringify(temps))
          this.resetTemps(temps)
        })
      } else {
        message.warning(res.message || '微信授权失败!')
        sessionStorage.setItem('wxTemplates' + appId, JSON.stringify([]))
      }
    })
  }
  resetTemps = (wxTemps) => {
@@ -169,6 +186,7 @@
      delete _verify.pre_func
    }
    if (_verify.wxNote !== 'true') {
      delete _verify.wxAppId
      delete _verify.wxTemplateId
      delete _verify.wxNoteLink
      delete _verify.wxNoteLinkUrl
@@ -250,6 +268,45 @@
    this.props.onChange(_verify)
  }
  onWxAppChange = (val) => {
    const { verify } = this.props
    let _verify = {...verify, wxAppId: val, wxNote: 'false'}
    delete _verify.wxTemplateId
    delete _verify.wxNoteLink
    delete _verify.wxNoteLinkUrl
    delete _verify.wxNoteMiniId
    delete _verify.wxNoteLinkMenuId
    delete _verify.wxNoteCallback
    delete _verify.wxCustomTempId
    _verify.wxNoteKeys = null
    if (this.state.selectTemp) {
      this.setState({selectTemp: null})
    }
    let _verify_ = fromJS(_verify).toJS()
    _verify_.wxNote = 'true'
    this.props.onChange(_verify)
    setTimeout(() => {
      this.props.onChange(_verify_)
      let wxTemps = sessionStorage.getItem('wxTemplates' + val)
      if (wxTemps) {
        wxTemps = JSON.parse(wxTemps)
        this.resetTemps(wxTemps)
      } else {
        this.getTemps(val)
      }
    }, 20)
  }
  onWxNoteKeyChange = (key, val) => {
    let _verify = fromJS(this.props.verify).toJS()
@@ -288,7 +345,7 @@
  render() {
    const { unionFields, verify, notes, emailCodes, card, appType, columns, fields } = this.props
    const { wxTemps, selectTemp } = this.state
    const { wxTemps, selectTemp, WXApps } = this.state
    const formItemLayout = {
      labelCol: {
        xs: { span: 24 },
@@ -635,6 +692,22 @@
              </Radio.Group>
            </Form.Item>
          </Col>
          {verify.wxNote === 'true' && WXApps ? <Col span={8}>
            <Form.Item label={
              <Tooltip placement="bottomLeft" title="请选择发送消息的公众号。">
                <QuestionCircleOutlined className="mk-form-tip" />
                公众号
              </Tooltip>
            } required>
              <Select value={verify.wxAppId || window.GLOB.WXAppID} onSelect={this.onWxAppChange}>
                {WXApps.map(option =>
                  <Select.Option key={option.appId} value={option.appId}>
                    {option.appName}
                  </Select.Option>
                )}
              </Select>
            </Form.Item>
          </Col> : null}
          {verify.wxNote === 'true' ? <Col span={8}>
            <Form.Item label="消息模板" required>
              <Select value={verify.wxTemplateId} onSelect={this.onWxTemplateChange}>
src/templates/zshare/verifycard/fullScripts/index.jsx
@@ -69,7 +69,7 @@
                position = <span style={{color: 'orange'}}>初始化</span>
              } else if (item.position === 'front') {
                position = <span style={{color: '#26C281'}}>sql前</span>
              } else {
              } else if (item.position === 'back') {
                position = <span style={{color: '#1890ff'}}>sql后</span>
              }
src/templates/zshare/verifycard/index.jsx
@@ -817,6 +817,8 @@
        if (_f.datatype) { // 自定义字段
          if (/decimal|int/ig.test(_f.datatype)) {
            _select.push(`@${_f.field}=1`)
          } else if (/date/ig.test(_f.datatype)) {
            _select.push(`@${_f.field}='1949-10-01'`)
          } else {
            _select.push(`@${_f.field}=''`)
          }
src/utils/utils-custom.js
@@ -1842,21 +1842,27 @@
          errors.push({ level: 0, detail: `按钮“${cell.label}”使用了创建凭证函数,需要选择行!`})
        }
      } else if (cell.intertype === 'custom' || cell.intertype === 'outer') {
        if (cell.callbackType === 'script' && (!cell.verify || !cell.verify.cbScripts || !cell.verify.cbScripts.filter(item => item.status !== 'false').length === 0)) {
        if (cell.callbackType === 'script' && (!cell.verify || !cell.verify.cbScripts || cell.verify.cbScripts.filter(item => item.status !== 'false').length === 0)) {
          errors.push({ level: 0, detail: `按钮“${cell.label}”使用了自定义脚本回调,回调脚本不可为空!`})
        } else if (cell.procMode === 'system' && cell.Ot === 'notRequired' && cell.verify && cell.verify.voucher && cell.verify.voucher.enabled) {
          errors.push({ level: 0, detail: `按钮“${cell.label}”使用了创建凭证函数,需要选择行!`})
        }
      }
    } else if (cell.OpenType === 'funcbutton' && cell.funcType === 'print') {
      if (!cell.verify || !cell.verify.printMode) {
        errors.push({ level: 0, detail: `按钮“${cell.label}”请完善验证信息!`})
      } else if (cell.intertype === 'system' && cell.verify.dataType === 'custom' && (!cell.verify.setting || cell.verify.columns.length === 0)) {
        errors.push({ level: 0, detail: `按钮“${cell.label}”使用了自定义打印数据,请设置数据源!`})
    } else if (cell.OpenType === 'funcbutton') {
      if (cell.funcType === 'print') {
        if (!cell.verify || !cell.verify.printMode) {
          errors.push({ level: 0, detail: `按钮“${cell.label}”请完善验证信息!`})
        } else if (cell.intertype === 'system' && cell.verify.dataType === 'custom' && (!cell.verify.setting || cell.verify.columns.length === 0)) {
          errors.push({ level: 0, detail: `按钮“${cell.label}”使用了自定义打印数据,请设置数据源!`})
        }
      } else if ((cell.funcType === 'refund' || cell.funcType === 'pay') && cell.payMode === 'system' && (!cell.verify || !cell.verify.scripts || cell.verify.scripts.filter(item => item.status !== 'false').length === 0)) {
        errors.push({ level: 0, detail: `按钮“${cell.label}”需添加自定义脚本!`})
      }
    } else if (cell.OpenType === 'innerpage' || cell.OpenType === 'outerpage') {
      if (!cell.pageTemplate) {
        errors.push({ level: 0, detail: `按钮“${cell.label}”页面类型设置错误!`})
      } else if (cell.pageTemplate === 'pay' && cell.payMode === 'system' && (!cell.verify || !cell.verify.scripts || cell.verify.scripts.filter(item => item.status !== 'false').length === 0)) {
        errors.push({ level: 0, detail: `按钮“${cell.label}”需添加自定义脚本!`})
      }
    }
  }
src/views/appcheck/index.jsx
@@ -84,6 +84,8 @@
              }
              cell.copyright = _param.copyright || ''
              cell.logo = _param.logo || ''
              cell.wxAppId = _param.wxAppId || ''
              cell.wxAppName = _param.wxAppName || ''
            }
            return cell
@@ -193,6 +195,8 @@
                    </Col>
                    <Col span={12}>
                      <div className="app-item">
                        {item.wxAppName ? <div className="label">关联公众号:</div> : null}
                        {item.wxAppName ? <div className="content">{item.wxAppName}</div> : null}
                      </div>
                    </Col>
                    <Col span={12}>
@@ -238,7 +242,7 @@
                    </Col>
                  </Row>
                  <div className="action">
                    <Paragraph style={{display: 'inline-block', margin: 0}} copyable={{ text: `${window.GLOB.baseurl}${item.typename === 'pad' ? 'mob' : item.typename}/index.html#/index/${this.state.selectApp.kei_no}/${item.typename !== 'pc' ? item.typename + '/' : ''}${item.lang}` }}></Paragraph>
                    <Paragraph style={{display: 'inline-block', margin: 0}} copyable={{ text: `${window.GLOB.baseurl}${item.typename === 'pad' ? 'mob' : item.typename}/index.html#/index/${this.state.selectApp.kei_no}/${item.typename !== 'pc' ? item.typename + '/' : ''}${item.lang}${item.wxAppId ? '/' + item.wxAppId : ''}` }}></Paragraph>
                  </div>
                </div>
              )
src/views/appmanage/index.jsx
@@ -485,6 +485,8 @@
              cell.share_des = _param.share_des || '' // 分享描述
              cell.share_url = _param.share_url || '' // 分享图片
              cell.share_link = _param.share_link || '' // 分享链接
              cell.wxAppId = _param.wxAppId || ''
              cell.wxAppName = _param.wxAppName || ''
              if (cell.adapter && (cell.adapter === 'true' || cell.adapter === 'false')) {
                cell.adapter = ''
@@ -672,7 +674,11 @@
    })
    // 子应用ID、typename、应用ID、CloudUserID、appkey、login_types(是否需要登录,已弃用)、link_type(是否使用短连接,已弃用)、role_type(是否使用角色管理)、lang、css(皮肤)、title(标题)、favicon(图标)、user_binding(用户绑定)、sms_id(短信模板ID)、自定义
    param.LText = sublist.map(item => `select '${item.ID}','${item.typename}','${selectApp.ID}','${sessionStorage.getItem('CloudUserID') || ''}','${window.GLOB.appkey || ''}','false','false','${item.role_type || 'true'}','${item.lang || 'zh-CN'}','${item.css || ''}','${item.title || ''}','${item.favicon || ''}','${item.user_binding || 'false'}','','${window.btoa(window.encodeURIComponent(JSON.stringify({userbind: item.userbind || '', instantMessage: item.instantMessage || '', apptype: item.apptype || '', delay: item.delay || 0, statusBarColor: item.statusBarColor || 'black', topHeight: item.topHeight || '', sysBgColor: item.sysBgColor || '#ffffff', direction: item.direction || 'vertical', adapter: item.adapter || '', share: item.share || '', share_des: item.share_des || '', share_url: item.share_url || '', share_link: item.share_link || ''})))}'`)
    param.LText = sublist.map(item => {
      let _par = this.getCusParam(item)
      return `select '${item.ID}','${item.typename}','${selectApp.ID}','${sessionStorage.getItem('CloudUserID') || ''}','${window.GLOB.appkey || ''}','false','false','${item.role_type || 'true'}','${item.lang || 'zh-CN'}','${item.css || ''}','${item.title || ''}','${item.favicon || ''}','${item.user_binding || 'false'}','','${window.btoa(window.encodeURIComponent(JSON.stringify(_par)))}'`
    })
    param.LText = param.LText.join(' union all ')
    param.LText = Utils.formatOptions(param.LText, 'x')
    
@@ -948,7 +954,11 @@
          return item
        })
        param.LText = selectApp.sublist.map(item => `select '${item.ID}','${item.typename}','${selectApp.ID}','${sessionStorage.getItem('CloudUserID') || ''}','${window.GLOB.appkey || ''}','false','false','${item.role_type || 'true'}','${item.lang || 'zh-CN'}','${item.css || ''}','${item.title || ''}','${item.favicon || ''}','${item.user_binding || 'false'}','','${window.btoa(window.encodeURIComponent(JSON.stringify({userbind: item.userbind || '', instantMessage: item.instantMessage || '', apptype: item.apptype || '', delay: item.delay || 0, statusBarColor: item.statusBarColor || 'black', topHeight: item.topHeight || '', sysBgColor: item.sysBgColor || '#ffffff', direction: item.direction || 'vertical', adapter: item.adapter || '', share: item.share || '', share_des: item.share_des || '', share_url: item.share_url || '', share_link: item.share_link || ''})))}'`)
        param.LText = selectApp.sublist.map(item => {
          let _par = this.getCusParam(item)
          return `select '${item.ID}','${item.typename}','${selectApp.ID}','${sessionStorage.getItem('CloudUserID') || ''}','${window.GLOB.appkey || ''}','false','false','${item.role_type || 'true'}','${item.lang || 'zh-CN'}','${item.css || ''}','${item.title || ''}','${item.favicon || ''}','${item.user_binding || 'false'}','','${window.btoa(window.encodeURIComponent(JSON.stringify(_par)))}'`
        })
        param.LText = param.LText.join(' union all ')
        param.LText = Utils.formatOptions(param.LText, 'x')
      }
@@ -985,6 +995,52 @@
        })
      })
    })
  }
  getCusParam = (item) => {
    let _par = {
      sysBgColor: item.sysBgColor || '#ffffff'
    }
    if (item.userbind) {
      _par.userbind = item.userbind
    }
    if (item.instantMessage) {
      _par.instantMessage = item.instantMessage
    }
    if (item.apptype) {
      _par.apptype = item.apptype
    }
    if (item.topHeight) {
      _par.topHeight = item.topHeight
    }
    if (item.typename === 'pad') {
      _par.direction = item.direction || 'vertical'
    }
    if (item.typename !== 'pc') {
      _par.statusBarColor = item.statusBarColor || 'black'
      _par.delay = item.delay || 0
    }
    if (item.adapter) {
      _par.adapter = item.adapter
    }
    if (item.share) {
      _par.share = item.share
    }
    if (item.share_des) {
      _par.share_des = item.share_des
    }
    if (item.share_url) {
      _par.share_url = item.share_url
    }
    if (item.share_link) {
      _par.share_link = item.share_link
    }
    if (item.wxAppId) {
      _par.wxAppId = item.wxAppId
      _par.wxAppName = item.wxAppName || item.wxAppId
    }
    return _par
  }
  submitSubCard = () => {
@@ -1041,7 +1097,11 @@
        return item
      })
      param.LText = sublist.map(item => `select '${item.ID}','${item.typename}','${selectApp.ID}','${sessionStorage.getItem('CloudUserID') || ''}','${window.GLOB.appkey || ''}','false','false','${item.role_type || 'true'}','${item.lang || 'zh-CN'}','${item.css || ''}','${item.title || ''}','${item.favicon || ''}','${item.user_binding || 'false'}','','${window.btoa(window.encodeURIComponent(JSON.stringify({userbind: item.userbind || '', instantMessage: item.instantMessage || '', apptype: item.apptype || '', delay: item.delay || 0, statusBarColor: item.statusBarColor || 'black', topHeight: item.topHeight || '', sysBgColor: item.sysBgColor || '#ffffff', direction: item.direction || 'vertical', adapter: item.adapter || '', share: item.share || '', share_des: item.share_des || '', share_url: item.share_url || '', share_link: item.share_link || ''})))}'`)
      param.LText = sublist.map(item => {
        let _par = this.getCusParam(item)
        return `select '${item.ID}','${item.typename}','${selectApp.ID}','${sessionStorage.getItem('CloudUserID') || ''}','${window.GLOB.appkey || ''}','false','false','${item.role_type || 'true'}','${item.lang || 'zh-CN'}','${item.css || ''}','${item.title || ''}','${item.favicon || ''}','${item.user_binding || 'false'}','','${window.btoa(window.encodeURIComponent(JSON.stringify(_par)))}'`
      })
      param.LText = param.LText.join(' union all ')
      param.LText = Utils.formatOptions(param.LText, 'x')
@@ -1188,8 +1248,8 @@
                    </Col>
                    <Col span={12}>
                      <div className="app-item">
                        {/* <div className="label">皮肤:</div>
                        <div className="content" style={{color: color}}>{css}</div> */}
                        {item.wxAppName ? <div className="label">关联公众号:</div> : null}
                        {item.wxAppName ? <div className="content">{item.wxAppName}</div> : null}
                      </div>
                    </Col>
                    <Col span={12}>
@@ -1234,7 +1294,7 @@
                    <Button type="link" onClick={() => this.setState({ selectSubApp: item, subVisible: 'edit' })} style={{color: '#8E44AD'}}>修改</Button>
                    <Button type="link" onClick={() => this.deleteSubApp(item)} style={{color: '#ff4d4f'}}>删除</Button>
                    <Button type="link" onClick={() => this.jumpApp(item)}>编辑应用</Button>
                    <Paragraph style={{display: 'inline-block', margin: 0}} copyable={{ text: `${window.GLOB.baseurl}${item.typename === 'pad' ? 'mob' : item.typename}/index.html#/index/${this.state.selectApp.kei_no}/${item.typename !== 'pc' ? item.typename + '/' : ''}${item.lang}` }}></Paragraph>
                    <Paragraph style={{display: 'inline-block', margin: 0}} copyable={{ text: `${window.GLOB.baseurl}${item.typename === 'pad' ? 'mob' : item.typename}/index.html#/index/${this.state.selectApp.kei_no}/${item.typename !== 'pc' ? item.typename + '/' : ''}${item.lang}${item.wxAppId ? '/' + item.wxAppId : ''}` }}></Paragraph>
                  </div>
                </div>
              )
src/views/appmanage/submutilform/index.jsx
@@ -20,7 +20,8 @@
  state = {
    typename: 'mob',
    adapters: [],
    exts: []
    exts: [],
    WXApps: null
  }
  UNSAFE_componentWillMount() {
@@ -47,7 +48,16 @@
      }
    }
    this.setState({typename, adapters, exts, langs: _langs})
    let apps = null
    if (window.GLOB.WXApps) {
      apps = window.GLOB.WXApps.filter(app => app.appType === 'public')
      if (apps.length === 0) {
        apps = null
      }
    }
    this.setState({typename, adapters, exts, langs: _langs, WXApps: apps})
  }
  /**
@@ -63,6 +73,10 @@
            values.user_binding = values.exts.includes('user_binding') ? 'true' : 'false'
            values.share = values.exts.includes('share') ? 'true' : 'false'
            delete values.exts
          }
          if (values.wxAppId) {
            let app = window.GLOB.WXApps.filter(app => app.appType === 'public' && values.wxAppId === app.appId)[0]
            values.wxAppName = app ? app.appName : values.wxAppId
          }
          resolve(values)
@@ -89,7 +103,7 @@
  render() {
    const { card, type } = this.props
    const { getFieldDecorator } = this.props.form
    const { typename, adapters, exts, langs } = this.state
    const { typename, adapters, exts, langs, WXApps } = this.state
    const formItemLayout = {
      labelCol: {
        xs: { span: 24 },
@@ -178,6 +192,22 @@
              )}
            </Form.Item>
          </Col> : null}
          {WXApps ? <Col span={12}>
            <Form.Item label={
              <Tooltip placement="topLeft" title="用户可通过此公众号进行支付及退款。">
                <QuestionCircleOutlined className="mk-form-tip" />
                关联公众号
              </Tooltip>
            }>
              {getFieldDecorator('wxAppId', {
                initialValue: card ? card.wxAppId : ''
              })(
                <Select allowClear>
                  {WXApps.map(item => <Select.Option key={item.appId} value={item.appId}>{item.appName}</Select.Option>)}
                </Select>
              )}
            </Form.Item>
          </Col> : null}
          {typename !== 'pc' && (adapters.includes('weixin') || adapters.includes('wxmini')) ? <Col span={12}>
            <Form.Item label={
              <Tooltip placement="topLeft" title="在公众号或小程序中,可添加绑定系统用户、自定义分享等功能,自定义分享设置后,当前子应用将默认使用此分享链接。">
src/views/appmanage/transmenu/index.jsx
@@ -313,6 +313,8 @@
        }
      }
      delete config.tbkey
      config.uuid = values.slice(0, 24) + tail
      config.MenuID = config.uuid
      config.open_edition = ''
src/views/design/header/index.jsx
@@ -344,10 +344,6 @@
    window.addEventListener('storage', (e) => {
      if (e.key === 'menuUpdate') {
        this.reload()
      } else if (e.key === 'wxTemplates') {
        if (e.newValue) {
          sessionStorage.setItem('wxTemplates', e.newValue)
        }
      }
    })
    MKEmitter.addListener('mkUpdateMenuList', this.reload)
src/views/design/header/transmenu/index.jsx
@@ -422,6 +422,8 @@
        config.style = config.style || {}
      }
      delete config.tbkey
      config.enabled = false
      config.MenuName = menu.label
      config.fstMenuId = menu.fstMenuId || ''
@@ -677,6 +679,8 @@
        config.style = config.style || {}
      }
      delete config.tbkey
      config.enabled = false
      config.MenuNo = temp.PrintTempNO || ''
      config.MenuName = temp.PrintTempName || ''
src/views/design/sidemenu/thdmenuplus/index.jsx
@@ -246,6 +246,8 @@
          config.components = MenuUtils.resetConfig(config.components, commonId)
          config.enabled = false
          delete config.tbkey
          param.LongParam = window.btoa(window.encodeURIComponent(JSON.stringify(config)))
        }
src/views/menudesign/index.jsx
@@ -98,7 +98,7 @@
      sessionStorage.setItem('MenuType', param.MenuType || 'custom')
      if (param.MenuType === 'billPrint' && param.lang) {
      if (param.lang) {
        sessionStorage.setItem('lang', param.lang)
      }
@@ -845,6 +845,8 @@
      } else {
        let urlparam = JSON.parse(window.decodeURIComponent(window.atob(this.props.match.params.param)))
        urlparam.type = 'admin'
        urlparam.lang = sessionStorage.getItem('lang')
        url = window.btoa(window.encodeURIComponent(JSON.stringify(urlparam)))
        config.tbkey = key
      }
src/views/mkiframe/index.jsx
@@ -75,6 +75,7 @@
            } else {
              sessionStorage.clear()
              this.props.history.replace('/login')
              window.location.reload()
            }
          })
        }
@@ -102,6 +103,7 @@
          sessionStorage.clear()
          sessionStorage.setItem('iframe', `/iframe/${menuId}/@loginuid@/${bid || ''}`)
          this.props.history.replace('/login')
          window.location.reload()
        }
      })
    }
src/views/mobdesign/index.jsx
@@ -120,6 +120,10 @@
          sessionStorage.removeItem('applangList')
        }
        if (param.wxAppId) {
          sessionStorage.setItem('wxAppId', param.wxAppId)
        }
        this.getAppMessage(param.MenuID)
      } else if (param.type === 'view') {
        window.GLOB.winWidth = 420
@@ -171,6 +175,11 @@
    MKEmitter.addListener('changePopview', this.initPopview)
    MKEmitter.addListener('triggerMenuSave', this.submitConfig)
    MKEmitter.addListener('changeEditMenu', this.changeEditMenu)
    if (sessionStorage.getItem('wxAppId')) {
      window.GLOB.WXAppID = sessionStorage.getItem('wxAppId')
    }
    setTimeout(() => {
      this.getRoleFields()
      setGLOBFuncs()
@@ -1486,7 +1495,7 @@
          typename: sessionStorage.getItem('typename') || '',
          adapter: sessionStorage.getItem('adapter') || '',
          sysBgColor: sessionStorage.getItem('sysBgColor') || '',
          MenuName: config.MenuName || '',
          MenuName: config.MenuName || ''
        }
        url = window.btoa(window.encodeURIComponent(JSON.stringify(urlparam)))
src/views/pay/index.jsx
@@ -17,54 +17,47 @@
  state = {
    orderId: '',
    orderNo: '',
    appid: '',
    logo: '',
    name: '',
    copyRight: '',
    icp: '',
    logo: window.GLOB.doclogo || '',
    name: sessionStorage.getItem('Full_Name') || '',
    copyRight: window.GLOB.copyRight || '',
    icp: window.GLOB.ICP || '',
    total: '',
    unit: '',
    qrcode: '',
    second: 60,
    overdue: false,
    overdone: false
    overdone: false,
    appId: ''
  }
  UNSAFE_componentWillMount () {
    let _urlparam = window.decodeURIComponent(window.atob(this.props.match.params.param))
    let _params = {}
    _urlparam.split('&').forEach(cell => {
      let _cell = cell.split('=')
      _params[_cell[0]] = _cell[1]
    })
    let param = JSON.parse(window.decodeURIComponent(window.atob(this.props.match.params.param)))
    if (!sessionStorage.getItem('LoginUID') && _params.LoginUID) {
      sessionStorage.setItem('LoginUID', _params.LoginUID)
    }
    if (!sessionStorage.getItem('UserID') && _params.userid) {
      sessionStorage.setItem('UserID', _params.userid)
    }
    let _appId = param.appId || window.GLOB.WXAppID || window.GLOB.WXminiAppID || ''
    this.setState({
      orderId: _params.ID,
      logo: _params.logo,
      name: _params.name,
      copyRight: _params.copyRight,
      icp: _params.icp
      orderId: param.ID,
      appId: _appId
    })
    if (_params.ID) {
      this.getOrder(_params.ID)
    } else {
    if (param.ID && _appId) {
      this.getOrder(param.ID, _appId)
    } else if (!param.ID) {
      notification.warning({
        top: 92,
        message: '未获取到订单ID!',
        duration: 5
      })
    } else if (!_appId) {
      notification.warning({
        top: 92,
        message: '未获取到应用ID!',
        duration: 5
      })
    }
  }
  getOrder = (Id) => {
  getOrder = (Id, appId) => {
    let param = {
      func: 's_get_weixin_pay_native',
      ID: Id
@@ -85,7 +78,6 @@
        }
        this.setState({
          appid: res.appid,
          orderNo: res.out_trade_no,
          total: _total,
          unit: res.amount && res.amount.currency === 'CNY' ? '元' : '元',
@@ -114,19 +106,12 @@
            duration: 5
          })
          return
        } else if (!res.appid) {
          notification.warning({
            top: 10,
            message: '未获取到应用ID!',
            duration: 5
          })
          return
        }
        Api.getWxNativePay({ 'out_biz_no': res.out_trade_no, 'out_open_id': res.appid }).then(result => {
          if (result.qrcode) {
        Api.getWxNativePay({ 'out_biz_no': res.out_trade_no, app_id: appId }).then(result => {
          if (result.status && result.code_url) {
            this.setState({
              qrcode: result.qrcode
              qrcode: result.code_url
            })
            setTimeout(this.resetSecond, 1000)
          } else {
@@ -135,7 +120,7 @@
            })
            notification.warning({
              top: 10,
              message: result.msg || '未获取到支付码!',
              message: result.message || '未获取到支付码!',
              duration: 5
            })
          }
@@ -198,7 +183,7 @@
  }
  resetQrcode = () => {
    const { appid, orderNo } = this.state
    const { orderNo, appId } = this.state
    if (!orderNo) {
      notification.warning({
@@ -207,12 +192,19 @@
        duration: 5
      })
      return
    } else if (!appId) {
      notification.warning({
        top: 10,
        message: '未获取到应用ID!',
        duration: 5
      })
      return
    }
    Api.getWxNativePay({ 'out_biz_no': orderNo, 'out_open_id': appid }).then(result => {
      if (result.qrcode) {
    Api.getWxNativePay({ 'out_biz_no': orderNo, app_id: appId }).then(result => {
      if (result.status && result.code_url) {
        this.setState({
          qrcode: result.qrcode,
          qrcode: result.code_url,
          overdue: false,
          second: 60
        })
@@ -220,7 +212,7 @@
      } else {
        notification.warning({
          top: 10,
          message: result.msg || '未获取到支付码!',
          message: result.message || '未获取到支付码!',
          duration: 5
        })
      }
src/views/pcdesign/index.jsx
@@ -115,6 +115,10 @@
          sessionStorage.removeItem('applangList')
        }
        if (param.wxAppId) {
          sessionStorage.setItem('wxAppId', param.wxAppId)
        }
        this.getAppMessage(param.MenuID)
      } else if (param.type === 'view') {
        this.setState({
@@ -152,6 +156,10 @@
    MKEmitter.addListener('changeEditMenu', this.changeEditMenu)
    MKEmitter.addListener('triggerMenuSave', this.triggerMenuSave)
    if (sessionStorage.getItem('wxAppId')) {
      window.GLOB.WXAppID = sessionStorage.getItem('wxAppId')
    }
    setTimeout(() => {
      this.getRoleFields()
      setGLOBFuncs()
src/views/tabledesign/index.jsx
@@ -88,6 +88,10 @@
    try {
      let param = JSON.parse(window.decodeURIComponent(window.atob(this.props.match.params.param)))
      if (param.lang) {
        sessionStorage.setItem('lang', param.lang)
      }
      this.setState({
        MenuId: param.MenuID,
        ParentId: param.ParentId || '',
@@ -589,6 +593,8 @@
        let urlparam = JSON.parse(window.decodeURIComponent(window.atob(this.props.match.params.param)))
        urlparam.type = 'admin'
        urlparam.MenuType = 'BaseTable'
        urlparam.lang = sessionStorage.getItem('lang')
        url = window.btoa(window.encodeURIComponent(JSON.stringify(urlparam)))
        config.tbkey = key
      }