king
2023-12-22 bcee29218364da52d9452803697b33a1067e7871
2023-12-22
6个文件已修改
1个文件已删除
2955 ■■■■■ 已修改文件
public/index.html 53 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/index.js 1084 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/index.js 278 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/router/index.js 48 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/login/index.jsx 869 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/login/logincloudform.jsx 90 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/login/loginform.jsx 533 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
public/index.html
@@ -5,60 +5,9 @@
    <meta name="renderer" content="webkit">
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <meta name="theme-color" content="#000000" />
    <link rel="shortcut icon" href="#">
    <link rel="shortcut icon" href="http://cloud.mk9h.cn/Content/images/upload/2020-04-01/2020040119095549823934_ced32a3ae29f2c80fe96c4857e2bf5a.png">
    <link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
    <title></title>
    <script>
      let _href = window.location.href.split('#')[0]
      let l_version = localStorage.getItem(_href + 'version')
      let _ctime = parseInt(new Date().getTime() / 1000)
      let _time = ''
      if (l_version) {
        let vers = l_version.split('-')
        l_version = vers[0]
        _time = +vers[1]
      }
      if (_time && _ctime - _time < 180) {
        let meta1 = document.createElement('meta')
        let meta2 = document.createElement('meta')
        let meta3 = document.createElement('meta')
        let meta4 = document.createElement('meta')
        meta1.content = '0'
        meta1.httpEquiv = 'Expires'
        meta2.content = 'no-cache'
        meta2.httpEquiv = 'Pragma'
        meta3.content = 'no-cache'
        meta3.httpEquiv = 'Cache-Control'
        meta4.content = 'no-cache'
        meta4.httpEquiv = 'Cache'
        document.getElementsByTagName('head')[0].appendChild(meta1)
        document.getElementsByTagName('head')[0].appendChild(meta2)
        document.getElementsByTagName('head')[0].appendChild(meta3)
        document.getElementsByTagName('head')[0].appendChild(meta4)
      } else {
        fetch('./manifest.json', { cache: 'no-cache'})
          .then(response => response.json())
          .then(res => {
            if (res && res.mk_version) {
              let version = res.mk_version
              let nocache = false
              if (l_version && version !== l_version) {
                nocache = true
                localStorage.setItem(_href + 'version', version + '-' + _ctime)
              } else if (!l_version) {
                localStorage.setItem(_href + 'version', version + '-' + (_ctime - 360))
              }
              if (nocache) {
                window.location.reload()
              }
            }
          })
      }
    </script>
  </head>
  <body>
    <noscript>You need to enable JavaScript to run this app.</noscript>
src/api/index.js
@@ -1,289 +1,37 @@
import axios from 'axios'
import qs from 'qs'
import { notification, Modal } from 'antd'
import md5 from 'md5'
import CryptoJS from 'crypto-js'
import jsSHA from 'jssha'
import moment from 'moment'
import Utils from '@/utils/utils.js'
import MKEmitter from '@/utils/events.js'
import CacheUtils from './cacheutils'
window.GLOB.IndexDB = null
window.GLOB.OuterToken = {}
window.GLOB.$error = false
let service = window.GLOB.service ? '-' + window.GLOB.service.replace('/', '') : ''
let db = `mkdb${service}`
if (window.indexedDB) {
  CacheUtils.openIndexDB(db)
}
axios.defaults.crossDomain = true
axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded;charset=UTF-8'
axios.defaults.withCredentials = false
axios.interceptors.response.use((response) => {
  if (response.data.ErrCode === 'LoginError') {
    if (window.GLOB.developing) {
      sessionStorage.setItem('devError', 'true')
      response.data.ErrCode = 'E'
      return Promise.resolve(response.data)
    } else if (response.config.url.indexOf('https://sso.mk9h.cn/webapi/dostars') > -1) {
      return Promise.reject(response.data)
    } else if (response.config.url.indexOf('https://epc.mk9h.cn/webapi/dostars') > -1) {
      return Promise.reject(response.data)
    }
    if (!window.GLOB.$error) {
      window.GLOB.$error = true
      Modal.destroyAll()
      Modal.error({
        title: response.data.message,
        okText: '知道了',
        onOk: () => {
          window.GLOB.$error = false
          sessionStorage.clear()
          if (!!(window.history && window.history.pushState)) {
            window.history.replaceState(null, null, window.location.href.split('#')[0] + '#/login')
            window.location.reload()
          }
        }
      })
    }
    return Promise.reject(response.data)
  } else {
    return Promise.resolve(response.data)
  }
  return Promise.resolve(response.data)
}, (error) => {
  let response = error.response || ''
  if (response && response.status) {
    notification.error({
      className: 'notification-custom-error',
      bottom: 0,
      message: '状态码-' + response.status + ',请联系管理员',
      placement: 'bottomRight',
      duration: 15
    })
  }
  return Promise.reject(response)
  return Promise.reject(error.response)
})
class Api {
  constructor() {
    axios.defaults.baseURL = window.GLOB.baseurl
  }
  /**
   * @description 使用dostar接口,跳过验证
   */
  dostarInterface (param) {
    param.userid = param.userid || ''
    return axios({
      url: `/webapi/dostar${param.func ? '/' + param.func : ''}`,
      method: 'post',
      data: JSON.stringify(param)
    })
  }
  /**
   * @description 微信业务请求
   */
  wxAccessToken (domain = '') {
    let _url = window.GLOB.baseurl + 'wxpay/getaccesstoken'
    if (domain) {
      _url = domain + 'wxpay/getaccesstoken'
    }
    return new Promise(resolve => {
      if (window.GLOB.accessToken.domain === domain && window.GLOB.accessToken.accessTime && (parseInt(new Date().getTime() / 1000) - window.GLOB.accessToken.accessTime < 30)) {
        resolve(window.GLOB.accessToken)
      } else {
        window.GLOB.accessToken = {domain}
        axios({
          url: _url,
          method: 'get'
        }).then(res => {
          if (res.oa_access_token || res.mini_access_token) {
            window.GLOB.accessToken.accessTime = parseInt(new Date().getTime() / 1000)
            window.GLOB.accessToken.oa_access_token = res.oa_access_token
            window.GLOB.accessToken.mini_access_token = res.mini_access_token
          }
          resolve(res)
        })
      }
    })
  }
  /**
   * @description 微信业务请求
   */
  wxNginxRequest (url, method, param) {
    let _url = url
    if (!/^http/.test(url)) {
      _url = window.GLOB.location + '/' + url
      if (process.env.NODE_ENV === 'production') {
        _url = document.location.origin + '/' + url
      }
      if (/^http:\/\/(qingqiumarket.cn|cloud.mk9h.cn|sso.mk9h.cn)/.test(_url)) {
        _url = window.GLOB.location + ':8080/' + url
        if (process.env.NODE_ENV === 'production') {
          _url = document.location.origin + ':8080/' + url
        }
      } else if (/^https:\/\/(qingqiumarket.cn|cloud.mk9h.cn|sso.mk9h.cn)/.test(_url)) {
        _url = window.GLOB.location + ':8443/' + url
        if (process.env.NODE_ENV === 'production') {
          _url = document.location.origin + ':8443/' + url
        }
      }
    }
    if (param) {
      return axios({
        url: _url,
        method,
        data: param
      })
    }
    return axios({
      url: _url,
      method
    })
  }
  /**
   * @description 直接请求
   */
  directRequest (params) {
    return axios(params)
  }
  /**
   * @description 游客登录
   */
  getTouristMsg (binding_type, appid, openid, memberid, scanId) {
    let _SessionUid = localStorage.getItem('SessionUid')
    if (!_SessionUid) { // 手动清除SessionUid时,实时生成
      _SessionUid = Utils.getuuid()
      localStorage.setItem('SessionUid', _SessionUid)
    }
    let param = {
      func: 's_visitor_login',
      timestamp: moment().format('YYYY-MM-DD HH:mm:ss'),
      SessionUid: _SessionUid,
      TypeCharOne: 'pc',
      kei_id: window.btoa(window.encodeURIComponent(window.GLOB.host)),
      appkey: window.GLOB.appkey || ''
    }
    let url = '/webapi/dologon/s_visitor_login'
    if (window.GLOB.mainSystemApi) {
      param.rduri = window.GLOB.mainSystemApi.replace(/\/webapi(.*)/, '/webapi/dologon/s_visitor_login')
    }
    if (binding_type === 'mk') {
      param.binding_type = 'mk'
      param.thd_party_member_id = memberid
      param.thd_party_openid = openid
      param.thd_party_appid = appid
      param.id = scanId
    } else if (binding_type === 'login_check') { // appid 此时为目标地址
      param.v_type = 'login_check'
      param.LoginUID = sessionStorage.getItem('LoginUID') || ''
      if (!param.rduri) {
        param.rduri = window.GLOB.baseurl + 'webapi/dologon/s_visitor_login'
      }
      if (appid) {
        url = appid.replace(/\/webapi(.*)/, '/webapi/dologon/s_visitor_login')
        param.linkurl = appid.replace(/\/webapi(.*)/, '/index.html')
      } else {
        param.linkurl = window.GLOB.linkurl
      }
    }
    param.LText = md5(window.btoa(_SessionUid + param.timestamp + (param.linkurl || '')))
    // param.secretkey = md5(param.LText + 'mingke' + param.timestamp) // v_type 为空时
    let solt = md5((window.GLOB.appkey + window.btoa(window.GLOB.appkey + 'mingke') + 'mingke').toLowerCase()).slice(-6).toUpperCase()
    param.v_type = param.v_type || 'Y'
    param.secretkey = md5(param.LText + solt + param.timestamp)
    return axios({
      url: url,
      method: 'post',
      data: JSON.stringify(param)
    })
  }
  /**
   * @description 手机号验证码登录
   */
  getphoneusermsg (phoneNo, checkcode, isCloud = false) {
    let param = {
      // func: 'webapi_login',
      mob: phoneNo,
      UserName: '',
      Password: '',
      check_code: checkcode,
      way_no: 'sms_vcode',
      systemType: window.GLOB.sysType,
      login_city: sessionStorage.getItem('city') || '',
      login_id_address: sessionStorage.getItem('ipAddress') || '',
      kei_id: window.btoa(window.encodeURIComponent(window.GLOB.host)),
      device_id: localStorage.getItem('SessionUid'),
      appkey: window.GLOB.appkey || ''
    }
    let url = '/webapi/dologon'
    if (isCloud) {
      param.debug = 'Y'
      if (window.GLOB.cloudServiceApi) {
        param.rduri = window.GLOB.cloudServiceApi.replace(/\/webapi(.*)/, '/webapi/dologon')
      }
    } else if (window.GLOB.mainSystemApi) {
      if (window.GLOB.sysType !== 'cloud' && window.GLOB.systemType !== 'production') {
        param.linkurl = window.GLOB.linkurl
      }
      param.rduri = window.GLOB.mainSystemApi.replace(/\/webapi(.*)/, '/webapi/dologon')
    }
    return axios({
      url,
      method: 'post',
      data: JSON.stringify(param)
    })
  }
  /**
   * @description 登录系统, 获取用户信息
   */
  getusermsg (username, password, isCloud = false) {
    let shim = +sessionStorage.getItem('sys_time_shim')
  getusermsg (username, password) {
    let param = {
      // func: 'webapi_login',
      UserName: username,
      systemType: window.GLOB.sysType,
      systemType: 'local',
      Type: 'S',
      login_city: sessionStorage.getItem('city') || '',
      login_id_address: sessionStorage.getItem('ipAddress') || '',
      kei_id: window.btoa(window.encodeURIComponent(window.GLOB.host)),
      login_city: '',
      login_id_address: '',
      kei_id: '',
      device_id: localStorage.getItem('SessionUid'),
      timestamp: moment().add(shim, 'seconds').format('YYYY-MM-DD HH:mm:ss'),
      timestamp: moment().format('YYYY-MM-DD HH:mm:ss'),
      appkey: window.GLOB.appkey || ''
    }
    
@@ -293,27 +41,9 @@
    param.Password = shaObj.getHash('HEX').toUpperCase()
    param.Password = md5(username + param.Password + param.timestamp)
    // Type: 'mk_' 时
    // param.Type = '公钥'
    // let shaObj = new jsSHA('SHA-1', 'TEXT')
    // shaObj.update(password)
    // param.Password = shaObj.getHash('HEX').toUpperCase()
    // param.Password = md5('私钥' + username + param.Password + param.timestamp)
    // Type: 'X' 时
    // param.Password = Utils.formatOptions(password)
    let url = '/webapi/dologon'
    if (isCloud) {
      param.debug = 'Y'
      if (window.GLOB.cloudServiceApi) {
        param.rduri = window.GLOB.cloudServiceApi.replace(/\/webapi(.*)/, '/webapi/dologon')
      }
    } else if (window.GLOB.mainSystemApi) {
      if (window.GLOB.sysType !== 'cloud' && window.GLOB.systemType !== 'production') {
        param.linkurl = window.GLOB.linkurl
      }
    if (window.GLOB.mainSystemApi) {
      param.rduri = window.GLOB.mainSystemApi.replace(/\/webapi(.*)/, '/webapi/dologon')
    }
@@ -321,802 +51,6 @@
      url,
      method: 'post',
      data: JSON.stringify(param)
    })
  }
  delCacheConfig (type = '') {
    let date = moment().subtract(7, 'days').format('YYYY-MM-DD HH:mm:ss')
    CacheUtils.delIndexDBCacheConfig(date, type)
  }
  writeCacheConfig (menuid, data, BID = '', id = '') {
    if (!menuid) return
    let date = moment().format('YYYY-MM-DD HH:mm:ss')
    let _data = data ? JSON.stringify(data) : ''
    let userid = sessionStorage.getItem('UserID') || ''
    CacheUtils.writeCacheInIndexDB({menuid: md5(menuid + userid + BID + id), BID: BID, id: id, CreateDate: date, LongParam: _data})
  }
  getLCacheConfig (menuid, minutes, BID = '', id = '') {
    return new Promise((resolve, reject) => {
      let limit = minutes ? moment().subtract(minutes, 'minutes').format('YYYY-MM-DD HH:mm:ss') : ''
      let userid = sessionStorage.getItem('UserID') || ''
      CacheUtils.getIndexDBCacheConfig(md5(menuid + userid + BID + id)).then(res => {
        if (res && res.LongParam) {
          resolve({data: JSON.parse(res.LongParam), valid: !limit || res.CreateDate > limit})
        } else {
          resolve({data: null, valid: false})
        }
      })
    })
  }
  /**
   * @description 获取系统版本信息
   */
  getAppVersion (reload) {
    if (!window.GLOB.IndexDB) {
      return Promise.reject()
    }
    let shim = +sessionStorage.getItem('sys_time_shim')
    let curTime = moment().add(shim, 'seconds').format('YYYY-MM-DD HH:mm:ss') + '.000'
    return new Promise((resolve, reject) => {
      CacheUtils.getIndexDBVersion().then(msg => {
        let param = {
          func: 's_get_app_version',
          modifydate: msg.createDate
        }
        if (window.GLOB.initVersion && sessionStorage.getItem('visitorUserID')) {
          param.userid = sessionStorage.getItem('visitorUserID')
          param.LoginUID = sessionStorage.getItem('visitorLoginUID')
        }
        param.TypeCharOne = ''
        param.typename = ''
        if (!msg.createDate && !msg.menuids) {
          CacheUtils.updateIndexDBversion({version: '1.00', createDate: curTime})
          resolve()
          return
        } else if (!msg.createDate || reload === true) {
          param.modifydate = curTime
          param.menuids = window.btoa(msg.menuids)
        } else if (msg.menuids) {
          let d = localStorage.getItem(db)
          if (!d || curTime.indexOf(d) === -1) {
            param.menuids = window.btoa(msg.menuids)
          }
          localStorage.setItem(db, curTime.substr(0, 10))
        }
        this.getSystemConfig(param).then(res => {
          if (!res.status) {
            reject()
            return
          }
          let list = res.menu_data || []
          if (res.menu_del) {
            list.push(...res.menu_del)
          }
          list = list.map(mid => mid.menuid)
          if (typeof(reload) === 'string' && !list.includes(reload)) {
            list.push(reload)
          }
          if (list.length > 0) {
            let clear = false
            let _appkey = window.GLOB.appkey.substr(-10)
            let reg = new RegExp(_appkey + '$', 'i')
            let reHome = list.includes('home_page_id')
            list.forEach(mid => {
              if (reg.test(mid)) {
                clear = true
              }
            })
            if (clear) {
              list = ''
            }
            CacheUtils.delIndexDBConfig(list)
            this.delCacheConfig('all')
            if (reHome) {
              MKEmitter.emit('reloadMenuView', 'home_page_id')
            }
          }
          CacheUtils.updateIndexDBversion({version: res.app_version || '1.00', createDate: curTime})
          resolve()
        })
      }, () => {
        reject()
      })
    })
  }
  /**
   * @description 更新系统版本信息,清空配置信息
   */
  updateAppVersion () {
    CacheUtils.delIndexDBConfig()
    CacheUtils.updateIndexDBversion()
    // CacheUtils.clearFuncs()
  }
  /**
   * @description 删除某个菜单配置信息
   */
  deleteMenuStorage (menuId) {
    CacheUtils.delIndexDBConfig(menuId)
  }
  /**
   * @description 获取或修改云端配置
   */
  getCloudConfig (param) {
    param.lang = param.lang || sessionStorage.getItem('lang') || ''
    param.appkey = param.appkey || window.GLOB.appkey || ''
    param.SessionUid = localStorage.getItem('SessionUid') || ''
    param.userid = param.userid || sessionStorage.getItem('CloudUserID') || ''
    param.LoginUID = param.LoginUID || sessionStorage.getItem('CloudLoginUID') || ''
    param = this.encryptParam(param)
    let url = window.GLOB.cloudServiceApi ? window.GLOB.cloudServiceApi : '/webapi/dostars'
    if (param.func) {
      url = url + '/' + param.func
    }
    return axios({
      url,
      method: 'post',
      data: JSON.stringify(param)
    })
  }
  /**
   * @description 获取或修改系统配置,增加appkey
   */
  getSystemFuncs (time) {
    let param = {
      func: 's_get_func_base_sso',
      update_date: time,
      userid: sessionStorage.getItem('UserID') || '',
      lang: sessionStorage.getItem('lang') || '',
      SessionUid: localStorage.getItem('SessionUid') || '',
      LoginUID: sessionStorage.getItem('LoginUID') || '',
      appkey: window.GLOB.appkey
    }
    let url = window.GLOB.mainSystemApi || '/webapi/dostars'
    param = this.encryptParam(param)
    return axios({
      url: `${url}/${param.func}`,
      method: 'post',
      data: JSON.stringify(param)
    })
  }
  /**
   * @description 获取或修改系统配置,增加appkey
   */
  getSystemConfig (param) {
    param.userid = param.userid || sessionStorage.getItem('UserID') || ''
    param.lang = param.lang || sessionStorage.getItem('lang') || ''
    param.SessionUid = localStorage.getItem('SessionUid') || ''
    param.LoginUID = param.LoginUID || sessionStorage.getItem('LoginUID') || ''
    param.appkey = param.appkey || window.GLOB.appkey
    let url = '/webapi/dostars'
    if (window.GLOB.mainSystemApi) {
      if (!window.GLOB.transfer) {
        url = window.GLOB.mainSystemApi
      } else {
        param.rduri = window.GLOB.mainSystemApi
      }
    }
    param = this.encryptParam(param)
    return axios({
      url: `${url}${param.func ? '/' + param.func : ''}`,
      method: 'post',
      data: JSON.stringify(param)
    })
  }
  /**
   * @description 获取系统配置,取值优先等级IndexDB、缓存、服务器
   */
  getCacheConfig (param) {
    param.userid = sessionStorage.getItem('UserID') || ''
    param.lang = param.lang || sessionStorage.getItem('lang') || ''
    param.SessionUid = localStorage.getItem('SessionUid') || ''
    param.LoginUID = sessionStorage.getItem('LoginUID') || ''
    param.appkey = param.appkey || window.GLOB.appkey || ''
    let url = '/webapi/dostars'
    if (window.GLOB.mainSystemApi) {
      if (!window.GLOB.transfer) {
        url = window.GLOB.mainSystemApi
      } else {
        param.rduri = window.GLOB.mainSystemApi
      }
    }
    let key = md5(param.MenuID + param.userid)
    if (window.GLOB.IndexDB) {
      return new Promise(resolve => {
        CacheUtils.getIndexDBMenuConfig(key).then(res => {
          resolve(res)
        }, () => {
          param = this.encryptParam(param)
          axios({
            url: `${url}${param.func ? '/' + param.func : ''}`,
            method: 'post',
            data: JSON.stringify(param)
          }).then(res => {
            if (res.status && window.GLOB.IndexDB) {
              let msg = {
                ...res,
                userid: param.userid,
                menuid: param.MenuID,
                id: key
              }
              CacheUtils.writeInIndexDB(msg)
            } else if (res.status) {
              window.GLOB.CacheMap.set(key, res)
            }
            resolve(res)
          })
        })
      })
    } else if (window.GLOB.CacheMap.has(key)) {
      return Promise.resolve(window.GLOB.CacheMap.get(key))
    } else {
      param = this.encryptParam(param)
      return new Promise(resolve => {
        axios({
          url: `${url}${param.func ? '/' + param.func : ''}`,
          method: 'post',
          data: JSON.stringify(param)
        }).then(res => {
          if (res.status) {
            window.GLOB.CacheMap.set(key, res)
          }
          resolve(res)
        })
      })
    }
  }
  /**
   * @description 获取本地系统配置
   */
  getLocalCacheConfig (param) {
    param.userid = sessionStorage.getItem('UserID') || ''
    param.lang = sessionStorage.getItem('lang') || ''
    param.SessionUid = localStorage.getItem('SessionUid') || ''
    param.LoginUID = sessionStorage.getItem('LoginUID') || ''
    param.appkey = window.GLOB.appkey || ''
    let _param  = md5(JSON.stringify(param))
    if (window.GLOB.CacheMap.has(_param)) {
      return Promise.resolve(window.GLOB.CacheMap.get(_param))
    } else {
      return Promise.resolve({ErrCode: 'S', LongParam: '', message: '', status: false})
    }
  }
  /**
   * @description dostars 参数加密
   */
  encryptParam (param) {
    param.nonc = Utils.getuuid()
    let keys = Object.keys(param).sort()
    let values = ''
    keys.forEach(key => {
      if (key === 'rduri' || key === 't') return
      if (param[key] === undefined) {
        delete param[key]
      } else if (typeof(param[key]) === 'object') {
        values += key + JSON.stringify(param[key])
      } else {
        values += key + param[key]
      }
    })
    param.sign = md5(values)
    param.t = new Date().getTime();
    ['arr_field', 'LText_field', 'custom_script', 'LText1', 'LText', 'LText2', 'DateCount'].forEach(key => {
      if (param[key]) {
        let val = param[key]
        delete param[key]
        param[key] = val
      }
    })
    return param
  }
  /**
   * @description 获取系统配置,优先从缓存中取值,增加appkey
   * @param {Object}  param   请求参数
   * @param {Boolean} cache   是否使用缓存
   */
  getSystemCacheConfig (param, cache = true) {
    param.userid = param.userid || sessionStorage.getItem('UserID') || ''
    param.lang = param.lang || sessionStorage.getItem('lang') || ''
    param.SessionUid = localStorage.getItem('SessionUid') || ''
    param.LoginUID = param.LoginUID || sessionStorage.getItem('LoginUID') || ''
    param.appkey = window.GLOB.appkey || ''
    let url = '/webapi/dostars'
    if (param.rduri && !window.GLOB.transfer) {
      url = param.rduri
      delete param.rduri
    }
    let _param = ''
    if (cache) {
      _param = JSON.parse(JSON.stringify(param)) // 缓存校验,去除时间和加密字符
      delete _param.timestamp
      delete _param.secretkey
      delete _param.open_key
      _param = JSON.stringify(_param)
      _param  = md5(_param)
    }
    if (cache && window.GLOB.CacheMap.has(_param)) {
      return Promise.resolve(window.GLOB.CacheMap.get(_param))
    } else {
      param = this.encryptParam(param)
      return new Promise(resolve => {
        axios({
          url: `${url}${param.func ? '/' + param.func : ''}`,
          method: 'post',
          data: JSON.stringify(param)
        }).then(res => {
          if (res.status) {
            window.GLOB.CacheMap.set(_param, res)
          }
          resolve(res)
        })
      })
    }
  }
  visitOuterSystem (param, _resolve, _reject) {
    let token = param.$token
    delete param.$token
    try {
      token = JSON.parse(token)
      token = token.message
      const key = CryptoJS.enc.Utf8.parse(window.GLOB.appkey.slice(-16))
      const iv = CryptoJS.enc.Utf8.parse('mksoft')
      let encryptedHexStr = CryptoJS.enc.Hex.parse(token)
      let _srcs = CryptoJS.enc.Base64.stringify(encryptedHexStr)
      let decrypt = CryptoJS.AES.decrypt(_srcs, key, { iv: iv, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7 })
      let decryptedStr = decrypt.toString(CryptoJS.enc.Utf8)
      token = decryptedStr.toString()
      token = JSON.parse(window.decodeURIComponent(window.atob(token)))
    } catch (e) {
      token = null
      _resolve({status: false, ErrCode: 'token_error', message: '接口信息解析失败!'})
    }
    if (!token) return
    let userid = ''
    let loginUid = ''
    let dataM = ''
    if (window.GLOB.OuterToken[token.interface]) {
      let msg = window.GLOB.OuterToken[token.interface]
      let seconds = Math.floor((new Date().getTime() - msg.timestamp) / 1000)
      if (seconds >= 3600) {
        delete window.GLOB.OuterToken[token.interface]
      } else {
        userid = msg.userid
        loginUid = msg.loginUid
        dataM = msg.dataM || ''
      }
    }
    // param.appkey = token.appkey || ''
    if (userid && loginUid) {
      param.dataM = dataM
      param.userid = userid
      param.LoginUID = loginUid
      param = this.encryptParam(param)
      axios({
        url: token.interface,
        method: 'post',
        data: JSON.stringify(param)
      }).then(res => {
        _resolve(res)
      }, () => {
        _reject()
      })
    } else {
      let _param = {
        UserName: token.username,
        systemType: window.GLOB.sysType,
        login_city: sessionStorage.getItem('city') || '',
        device_id: token.appkey || '',
        timestamp: moment().format('YYYY-MM-DD HH:mm:ss'),
        Type: token.publicKey,
        appkey: token.appkey || ''
      }
      let shaObj = new jsSHA('SHA-1', 'TEXT')
      shaObj.update(token.password)
      _param.Password = shaObj.getHash('HEX').toUpperCase()
      _param.Password = md5(token.privateKey + token.username + _param.Password + _param.timestamp)
      let url = token.interface.replace(/\/webapi(.*)/, '/webapi/dologon')
      if (token.ssoInterface) {
        _param.rduri = token.ssoInterface.replace(/\/webapi(.*)/, '/webapi/dologon')
      }
      axios({
        url,
        method: 'post',
        data: JSON.stringify(_param)
      }).then(result => {
        if (result.status) {
          window.GLOB.OuterToken[token.interface] = {
            userid: result.UserID,
            loginUid: result.LoginUID,
            timestamp: new Date().getTime(),
            dataM: result.dataM ? 'Y' : ''
          }
          param.dataM = result.dataM ? 'Y' : ''
          param.userid = result.UserID
          param.LoginUID = result.LoginUID
          param = this.encryptParam(param)
          axios({
            url: token.interface,
            method: 'post',
            data: JSON.stringify(param)
          }).then(res => {
            _resolve(res)
          }, () => {
            _reject()
          })
        } else {
          _resolve(result)
        }
      }, (e) => {
        if (!e || !e.status) {
          let msg = '网络连接不正常。'
          if (/^http:/.test(token.interface) && /https:/.test(window.location.protocol)) {
            msg = '网络连接不正常,接口地址可能不支持https。'
          }
          _resolve({status: false, ErrCode: 'E', message: msg})
        } else {
          _reject()
        }
      })
    }
  }
  /**
   * @description 获取业务通用接口
   * 访问 'https://sso.mk9h.cn/webapi/dostars'或云端时,传入userid、LoginUID
   */
  genericInterface (param) {
    param.userid = param.userid || sessionStorage.getItem('UserID') || ''
    param.lang = param.lang || sessionStorage.getItem('lang') || ''
    param.SessionUid = localStorage.getItem('SessionUid') || ''
    param.LoginUID = param.LoginUID || sessionStorage.getItem('LoginUID') || ''
    param.appkey = window.GLOB.appkey || ''
    if (param.$token === '') {
      return Promise.resolve({status: false, ErrCode: 'token_error', message: '接口地址尚未设置!'})
    } else if (param.$token) {
      return new Promise((resolve, reject) => this.visitOuterSystem(param, resolve, reject))
    }
    if (['sPC_TableData_InUpDe', 'sPC_TableData_InUpDe_debug'].includes(param.func)) {
      param.username = sessionStorage.getItem('User_Name') || ''
      param.fullname = sessionStorage.getItem('Full_Name') || ''
    }
    if (param.rduri && /\s|\n/.test(param.rduri)) {
      param.rduri = param.rduri.replace(/\s|\n/g, '')
      if (!param.rduri) {
        delete param.rduri
      }
    }
    if (param.$login) {
      let rduri = param.rduri || ''
      delete param.$login
      delete param.rduri
      param = this.encryptParam(param)
      let time = +sessionStorage.getItem(rduri)
      let c_time = Math.round(new Date().getTime() / 1000)
      if (time && c_time - time <= 1800) {
        sessionStorage.setItem(rduri, c_time)
        return new Promise((resolve, reject) => {
          axios({
            url: `${rduri}${param.func ? '/' + param.func : ''}`,
            method: 'post',
            data: JSON.stringify(param)
          }).then(result => {
            if (result && result.ErrCode === 'LoginError') {
              sessionStorage.removeItem(rduri)
            }
            resolve(result)
          }, () => {
            reject()
          })
        })
      }
      return new Promise((resolve, reject) => {
        this.getTouristMsg('login_check', rduri).then(res => {
          if (res.status) {
            sessionStorage.setItem(rduri, c_time)
            axios({
              url: `${rduri}${param.func ? '/' + param.func : ''}`,
              method: 'post',
              data: JSON.stringify(param)
            }).then(result => {
              resolve(result)
            }, () => {
              reject()
            })
          } else {
            resolve(res)
          }
        }, (e) => {
          if (!e || !e.status) {
            let msg = '网络连接不正常。'
            if (/^http:/.test(rduri) && /https:/.test(window.location.protocol)) {
              msg = '网络连接不正常,接口地址可能不支持https。'
            }
            resolve({status: false, ErrCode: 'E', message: msg})
          } else {
            reject()
          }
        })
      })
    } else {
      let url = '/webapi/dostars'
      if (param.rduri && !window.GLOB.transfer && /\/dostars/.test(param.rduri) && param.func !== 'webapi_ChangeUser') {
        url = param.rduri
        delete param.rduri
      }
      param = this.encryptParam(param)
      return axios({
        url: `${url}${param.func ? '/' + param.func : ''}`,
        method: 'post',
        data: JSON.stringify(param)
      })
    }
  }
  /**
   * @description 上传base64
   * @param {String} base64 base64图片编码
   */
  fileuploadbase64 (param) {
    param.func = ''
    param.BasePath = 'Content/Upload'
    param.lang = sessionStorage.getItem('lang') || ''
    param.appkey = window.GLOB.appkey || ''
    param.SessionUid = localStorage.getItem('SessionUid') || ''
    param.userid = param.userid || sessionStorage.getItem('UserID') || ''
    param.LoginUID = param.LoginUID || sessionStorage.getItem('LoginUID') || ''
    param = this.encryptParam(param)
    let url = '/webapi/SaveBase64Image'
    if (param.rduri) {
      param.rduri = param.rduri.replace(/webapi(.*)$/, 'webapi/SaveBase64Image')
      if (/\s|\n/.test(param.rduri)) {
        param.rduri = param.rduri.replace(/\s|\n/g, '')
        if (!param.rduri) {
          delete param.rduri
        }
      }
    }
    if (param.rduri && !window.GLOB.transfer) {
      url = param.rduri
      delete param.rduri
    }
    return axios({
      url,
      method: 'post',
      data: JSON.stringify(param)
    })
  }
  /**
   * @description 大文件上传
   */
  getLargeFileUpload (param) {
    return axios({
      url: '/webapi/doupload',
      method: 'post',
      headers: { 'Content-Type': 'multipart/form-data' },
      data: param
    })
  }
  /**
   * @description 查询文件是否已上传
   */
  getFilePreUpload (param) {
    return axios({
      url: '/webapi/dopreload',
      method: 'post',
      headers: { 'Content-Type': 'multipart/form-data' },
      data: param
    })
  }
  /**
   * @description oss文件上传
   */
  fileOssUpload (param) {
    let _url = window.GLOB.location + '/file/oss/upload'
    if (process.env.NODE_ENV === 'production') {
      _url = document.location.origin + '/file/oss/upload'
    }
    if (/^http:\/\/(qingqiumarket.cn|cloud.mk9h.cn|sso.mk9h.cn)/.test(_url)) {
      _url = window.GLOB.location + ':8080/file/oss/upload'
      if (process.env.NODE_ENV === 'production') {
        _url = document.location.origin + ':8080/file/oss/upload'
      }
    } else if (/^https:\/\/(qingqiumarket.cn|cloud.mk9h.cn|sso.mk9h.cn)/.test(_url)) {
      _url = window.GLOB.location + ':8443/file/oss/upload'
      if (process.env.NODE_ENV === 'production') {
        _url = document.location.origin + ':8443/file/oss/upload'
      }
    }
    return axios({
      url: _url,
      method: 'post',
      headers: { 'Content-Type': 'multipart/form-data' },
      data: param
    })
  }
  /**
   * @description 获取微信支付二维码
   */
  getWxNativePay (param) {
    let _url = window.GLOB.baseurl + 'wxpay/wxNativePay'
    return axios({
      url: _url,
      method: 'post',
      data: qs.stringify(param)
    })
  }
  postekPrint (data) {
    return axios({
      url: 'http://127.0.0.1:888/postek/print',
      method: 'post',
      data: qs.stringify(data)
    })
  }
  /**
   * @description sql检验
   */
  sDebug (sql, rduri = null) {
    let param = {
      func: 's_debug_sql',
      exec_type: 'y',
      timestamp: moment().format('YYYY-MM-DD HH:mm:ss'),
      userid: sessionStorage.getItem('UserID') || '',
      lang: sessionStorage.getItem('lang') || '',
      SessionUid: localStorage.getItem('SessionUid') || '',
      LoginUID: sessionStorage.getItem('LoginUID') || '',
      appkey: window.GLOB.appkey || ''
    }
    let id = Utils.getuuid()
    sql = sql.replace(/@time_id@/ig, `'${id}'`)
    if (window.GLOB.externalDatabase !== null) {
      sql = sql.replace(/@db@/ig, window.GLOB.externalDatabase)
    }
    console.info(`/* sql 验证 */\n${sql.replace(/\n\s{6,20}/ig, '\n')}`)
    sql = sql.replace(/\n/ig, ' ')
    param.LText = Utils.formatOptions(sql)
    param.secretkey = Utils.encrypt('', param.timestamp)
    param = this.encryptParam(param)
    let url = '/webapi/dostars'
    if (rduri) {
      url = rduri
    }
    let timer = setTimeout(() => {
      let _param = {
        func: 's_debug_sql_cancel',
        userid: sessionStorage.getItem('UserID') || '',
        lang: sessionStorage.getItem('lang') || '',
        SessionUid: localStorage.getItem('SessionUid') || '',
        LoginUID: sessionStorage.getItem('LoginUID') || '',
        appkey: window.GLOB.appkey || ''
      }
      _param = this.encryptParam(_param)
      axios({
        url: `${url}/s_debug_sql_cancel`,
        method: 'post',
        data: JSON.stringify(_param)
      })
    }, 20000)
    return new Promise(resolve => {
      axios({
        url: `${url}/s_debug_sql`,
        method: 'post',
        data: JSON.stringify(param)
      }).then(res => {
        clearTimeout(timer)
        if (/Shared Memory Provider|会话处于终止状态|当前命令发生了严重错误/.test(res.message)) {
          res.message = '验证失败,请检查SQL中是否存在死循环。'
        } else if (res.message.indexOf('EXECUTE 后的事务计数指示 BEGIN 和 COMMIT 语句的数目不匹配。上一计数 = 1,当前计数 = 0') > -1) {
          res.ErrCode = '-2'
        }
        resolve(res)
      }, () => {
        clearTimeout(timer)
        resolve({status: false, ErrCode: 'E', message: '验证失败:1请检查SQL中是否存在死循环;2请检查网络连接是否正常。'})
      })
    })
  }
}
src/index.js
@@ -1,11 +1,8 @@
import React from 'react'
import ReactDOM from 'react-dom'
import Route from './router'
import md5 from 'md5'
import * as serviceWorker from './serviceWorker'
import options, { styles } from '@/store/options.js'
import '@/assets/css/main.scss'
import '@/assets/css/action.scss'
import '@/assets/css/viewstyle.scss'
if (!localStorage.getItem('SessionUid')) {
@@ -34,284 +31,25 @@
  .then(config => {
    if (!config) return
    if (config.defaultApp) {
      if ((navigator.userAgent.match(/(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone)/i))) {
        window.location.replace(window.location.href.split(/(index.html)+/ig)[0].replace('admin/', '') + 'mob/index.html#/index')
        return
      }
    }
    let GLOB = {}
    GLOB.appId = config.appId || ''
    GLOB.lineColor = config.lineColor || ''
    GLOB.licenseKey = config.licenseKey || ''
    GLOB.probation = false
    GLOB.watermark = config.watermark + '' !== 'false'
    GLOB.transfer = config.transfer + '' === 'true'
    GLOB.keepKey = config.keepPassword + '' !== 'false'
    GLOB.nginx = config.nginx + '' === 'true'
    GLOB.WXAppID = config.WXAppID || ''
    GLOB.WXminiAppID = config.WXminiAppID || ''
    GLOB.WXNotice = config.WXNotice + '' === 'true'
    GLOB.accessToken = {}
    GLOB.mkHS = false
    GLOB.debugger = false
    GLOB.dataFormat = false
    GLOB.upStatus = false
    GLOB.navBar = 'shutter' // 默认为百叶窗
    GLOB.style = 'bg_black_style_blue'
    GLOB.appkey = config.appkey
    GLOB.sysType = options.sysType
    if (GLOB.sysType !== 'cloud') {
      GLOB.cloudServiceApi = options.cdomain + '/webapi/dostars'
    }
    GLOB.mainSystemApi = 'https://sso.mk9h.cn/cloud/webapi/dostars'
    if (sessionStorage.getItem('externalDatabase')) {
      GLOB.externalDatabase = `[${sessionStorage.getItem('externalDatabase')}]..`
    } else if (config.externalDatabase + '' !== 'false' && config.externalDatabase !== undefined) {
      GLOB.externalDatabase = config.externalDatabase ? `[${config.externalDatabase}]..` : ''
    } else {
      GLOB.externalDatabase = null
    }
    document.body.className = 'mk-blue-black'
    document.title = 'MinkeSoft'
    // 只有业务系统才可以设置为正式系统
    if (GLOB.sysType === 'local' && (config.systemType === 'official' || config.systemType === 'production')) {
      GLOB.systemType = 'production'
      if (config.probation && /^20\d{2}-\d{2}-\d{2}$/.test(config.probation) && new Date(config.probation).getTime() > new Date().getTime()) {
        GLOB.probation = true
      }
    GLOB.location = config.host
    GLOB.service = config.service
    GLOB.baseurl = GLOB.location + '/' + GLOB.service
      if (!config.mainSystemApi) {
        document.getElementById('root').innerHTML = '<div style="text-align: center; font-size: 30px; margin-top: 40vh;">系统未设置单点地址,请联系管理员!</div>'
        return
      } else if (/http(s?):\/\/sso.mk9h.cn\/cloud/ig.test(config.mainSystemApi)) {
        document.getElementById('root').innerHTML = '<div style="text-align: center; font-size: 30px; margin-top: 40vh;">正式系统不可使用 http://sso.mk9h.cn/cloud 做为单点地址,请联系管理员!</div>'
        return
      } else if (/http(s?):\/\/cloud.mk9h.cn/ig.test(config.mainSystemApi)) {
        document.getElementById('root').innerHTML = '<div style="text-align: center; font-size: 30px; margin-top: 40vh;">正式系统不可使用 http://cloud.mk9h.cn 做为单点地址,请联系管理员!</div>'
        return
      }
    } else if (GLOB.sysType === 'local') {
      GLOB.probation = true
      GLOB.debugger = true
      GLOB.systemType = ''
      GLOB.upStatus = config.updateStatus + '' !== 'false'
      // GLOB.mainSystemApi = 'https://cloud.positecgroup.com/webapi/dostars'
      GLOB.mainSystemApi = 'https://sso.mk9h.cn/cloud/webapi/dostars'
      if (!/^https/.test(window.location.protocol)) { // https转换
        GLOB.mainSystemApi = 'http://sso.mk9h.cn/cloud/webapi/dostars'
      }
      if (GLOB.watermark) {
        GLOB.dataFormat = true
      }
    } else {
      GLOB.systemType = ''
      GLOB.mainSystemApi = ''
    }
    if (GLOB.sysType !== 'cloud') {
      if (config.appkey === options.cakey) {
        document.getElementById('root').innerHTML = '<div style="text-align: center; font-size: 30px; margin-top: 40vh;">不可使用云端appkey,请联系管理员!</div>'
        return
      }
    }
    if (GLOB.sysType === 'cloud') { // cloud不可设置单点服务器地址,云端appkey为系统设置
      GLOB.appkey = options.cakey
      GLOB.appId = options.caId
      GLOB.WXNotice = false
    } else if (GLOB.sysType === 'SSO') { // sso不可设置单点服务器地址
      GLOB.appkey = config.appkey
    } else if (GLOB.sysType === 'local') { // 业务系统
      GLOB.appkey = config.appkey
      if (GLOB.systemType === 'production') {
        let systemApi = config.mainSystemApi
        if (/index.html/ig.test(systemApi)) {
          systemApi = systemApi.replace(/index.html.*/ig, 'webapi/dostars')
        } else if (!/webapi\/dostars$/ig.test(systemApi)) {
          systemApi = systemApi.replace(/\/?$/, '/webapi/dostars')
        }
        if (/^https/.test(window.location.protocol) && /^http:/.test(systemApi) && !GLOB.transfer) {
          systemApi = systemApi.replace(/^http:/, 'https:')
        }
        GLOB.mainSystemApi = systemApi
      }
    }
    if (/#\/hs$/.test(window.location.href)) { // hs下不打印脚本
      GLOB.debugger = false
      if (GLOB.mainSystemApi) {
        GLOB.localSystemApi = GLOB.mainSystemApi
        GLOB.mainSystemApi = ''
      }
      if (GLOB.cloudServiceApi) {
        GLOB.mainSystemApi = GLOB.cloudServiceApi
      }
    }
    let _href = window.location.href.split('#')[0]
    let _systemMsg = localStorage.getItem(_href + 'system')
    let className = 'mk-blue-black'
    if (_systemMsg) {
      try {
        _systemMsg = JSON.parse(window.decodeURIComponent(window.atob(_systemMsg)))
        GLOB.platTitle = _systemMsg.platTitle
        GLOB.platName = _systemMsg.platName
        GLOB.favicon = _systemMsg.favicon
        GLOB.loginlogo = _systemMsg.loginlogo
        GLOB.copyRight = _systemMsg.copyRight
        GLOB.ICP = _systemMsg.ICP
        GLOB.bgImage = _systemMsg.bgImage
        GLOB.mainlogo = _systemMsg.mainlogo
        GLOB.doclogo = _systemMsg.doclogo
        GLOB.webSite = _systemMsg.webSite
        GLOB.style = _systemMsg.style || 'bg_black_style_blue'
        GLOB.showline = _systemMsg.showline || ''
        GLOB.navBar = _systemMsg.navBar || 'shutter'
        GLOB.appVersion = _systemMsg.app_version || ''
        sessionStorage.setItem('appname', _systemMsg.appname || '')
        let levels = [30, 10, 20, 40, 50, 60, 70, 80, 90, 100]
        levels.some(m => {
          if (_systemMsg.Member_Level === md5('mksoft' + GLOB.appkey + m)) {
            GLOB.memberLevel = m
            return true
          }
          return false
        })
        if (GLOB.favicon) {
          let link = document.querySelector("link[rel*='icon']") || document.createElement('link')
          link.type = 'image/x-icon'
          link.rel = 'shortcut icon'
          link.href = GLOB.favicon
          document.getElementsByTagName('head')[0].appendChild(link)
        }
        if (styles[GLOB.style]) {
          className = styles[GLOB.style] + ' ' + (GLOB.showline === 'false' ? 'hidden-split-line' : '')
        }
      } catch (e) {
        console.warn('Parse Failure')
      }
    }
    document.body.className = className
    if (/^https/.test(window.location.protocol)) { // https转换
      let meta = document.createElement('meta')
      meta.content = 'upgrade-insecure-requests'
      meta.httpEquiv = 'Content-Security-Policy'
      document.getElementsByTagName('head')[0].appendChild(meta)
    }
    document.title = GLOB.platTitle || ''
    if (config.filter === 'true' || (/^20\d{2}-\d{2}-\d{2}$/.test(config.filter) && new Date(config.filter).getTime() + 86400000 >= new Date().getTime())) {
      GLOB.filter = true
    }
    if (process.env.NODE_ENV === 'production') { // 用于校验是否存在开发权限
      let _service = window.location.href.replace(/\/admin(.*)/ig, '').replace(new RegExp(document.location.origin + '/?', 'ig'), '')
      GLOB.service = _service ? _service + '/' : ''
      GLOB.host = window.location.host + (_service ? '_' + _service : '')
      GLOB.baseurl = document.location.origin + '/' + GLOB.service
      GLOB.linkurl = GLOB.baseurl + 'index.html'
    } else {
      GLOB.location = config.host
      GLOB.service = config.service
      GLOB.host = config.host.replace(/http(s)?:\/\//ig, '') + (config.service ? '_' + config.service.replace(/\//ig, '') : '')
      GLOB.baseurl = GLOB.location + '/' + GLOB.service
      GLOB.linkurl = GLOB.baseurl + 'index.html'
      GLOB.dataFormat = false
      let mark = sessionStorage.getItem('system_mark')
      let _mark = `sys_${GLOB.service.replace('/', '') || 'service'}`
      if (mark && mark !== _mark) {
        sessionStorage.clear()
      }
      sessionStorage.setItem('system_mark', _mark)
    }
    let lang = localStorage.getItem(_href + 'lang') || (config.defaultLang !== 'en-US' ? 'zh-CN' : 'en-US')
    sessionStorage.setItem('lang', lang)
    GLOB.mkActions = {}  // 按钮权限集
    Object.defineProperty(GLOB, 'appId', {
      writable: false,
      value: GLOB.appId
    })
    Object.defineProperty(GLOB, 'appkey', {
      writable: false,
      value: GLOB.appkey
    })
    Object.defineProperty(GLOB, 'systemType', {
      writable: false,
      value: GLOB.systemType
    })
    Object.defineProperty(GLOB, 'mainSystemApi', {
      writable: false,
      value: GLOB.mainSystemApi
    })
    Object.defineProperty(GLOB, 'linkurl', {
      writable: false,
      value: GLOB.linkurl
    })
    Object.defineProperty(GLOB, 'sysType', {
      writable: false,
      value: GLOB.sysType
    })
    Object.defineProperty(GLOB, 'cloudServiceApi', {
      writable: false,
      value: GLOB.cloudServiceApi || ''
    })
    if (GLOB.memberLevel) {
      Object.defineProperty(GLOB, 'memberLevel', {
        writable: false,
        value: GLOB.memberLevel
      })
    } else {
      GLOB.memberLevel = 0
    }
    if (GLOB.sysType === 'cloud') {
      Object.defineProperty(GLOB, 'debugger', {
        writable: false,
        value: GLOB.debugger
      })
      GLOB.breakpoint = false
    } else {
      if (sessionStorage.getItem('breakpoint')) {
        GLOB.debugger = true
        GLOB.breakpoint = sessionStorage.getItem('breakpoint')
      } else {
        GLOB.breakpoint = false
      }
    }
    sessionStorage.setItem('lang', 'zh-CN')
    Object.defineProperty(window, 'GLOB', {
      writable: false,
      value: GLOB
    })
    window.GLOB.CacheMap = new Map()     // 缓存配置信息
    window.GLOB.CacheVoucher = new Map() // 缓存凭证信息
    window.GLOB.UserCacheMap = new Map() // 缓存用户自定义设置
    window.GLOB.CacheData = new Map()    // 存储选中数据
    window.GLOB.SearchBox = new Map()    // 存储搜索条件
    window.GLOB.SyncData = new Map()     // 存储同步查询数据
    window.GLOB.mkThdMenus = new Map()   // 三级菜单
    render(Route)
  })
src/router/index.js
@@ -4,56 +4,10 @@
import asyncLoadComponent from '@/utils/asyncLoadComponent'
const Login = asyncLoadComponent(() => import('@/views/login'))
const Main = asyncLoadComponent(() => import('@/views/main'))
const Sso = asyncLoadComponent(() => import('@/views/sso'))
const Pay = asyncLoadComponent(() => import('@/views/pay'))
const MainParams = asyncLoadComponent(() => import('@/views/mainparams'))
const Design = asyncLoadComponent(() => import('@/views/design'))
const NotFound = asyncComponent(() => import('@/views/404'))
const AppManage = asyncLoadComponent(() => import('@/views/appmanage'))
const AppCheck = asyncLoadComponent(() => import('@/views/appcheck'))
const PCDesign = asyncLoadComponent(() => import('@/views/pcdesign'))
const MobDesign = asyncLoadComponent(() => import('@/views/mobdesign'))
const ImDesign = asyncLoadComponent(() => import('@/views/imdesign'))
const MenuDesign = asyncLoadComponent(() => import('@/views/menudesign'))
const BaseDesign = asyncLoadComponent(() => import('@/views/basedesign'))
const TableDesign = asyncLoadComponent(() => import('@/views/tabledesign'))
const BillPrint = asyncLoadComponent(() => import('@/views/billprint'))
const PrintT = asyncLoadComponent(() => import('@/views/printTemplate'))
const Interface = asyncLoadComponent(() => import('@/views/interface'))
const RoleManage = asyncLoadComponent(() => import('@/views/rolemanage'))
const SystemFunc = asyncLoadComponent(() => import('@/views/systemfunc'))
const SystemProc = asyncLoadComponent(() => import('@/views/systemproc'))
const MkIframe = asyncLoadComponent(() => import('@/views/mkiframe'))
const routers = [
  {path: '/login', name: 'login', component: Login},
  {path: '/main', name: 'main', component: Main},
  {path: '/pay/:param', name: 'pay', component: Pay},
  {path: '/print/:param', name: 'print', component: PrintT},
  {path: '/ssologin/:param', name: 'ssologin', component: Sso},
  {path: '/design', name: 'design', component: Design},
  {path: '/appmanage', name: 'appmanage', component: AppManage},
  {path: '/appcheck', name: 'appcheck', component: AppCheck},
  {path: '/pcdesign/:param', name: 'pcdesign', component: PCDesign},
  {path: '/mobdesign/:param', name: 'mobdesign', component: MobDesign},
  {path: '/imdesign/:param', name: 'imdesign', component: ImDesign},
  {path: '/menudesign/:param', name: 'menudesign', component: MenuDesign},
  {path: '/basedesign/:param', name: 'basedesign', component: BaseDesign},
  {path: '/tabledesign/:param', name: 'tabledesign', component: TableDesign},
  {path: '/billprint/:param', name: 'billprint', component: BillPrint},
  {path: '/docprint/:menuId', name: 'docprint', component: BillPrint},
  {path: '/docprint/:menuId/:id', name: 'docprint', component: BillPrint},
  {path: '/tab/:menuId', name: 'tab', component: MainParams},
  {path: '/role/:param', name: 'role', component: RoleManage},
  {path: '/hs', name: 'hs', component: SystemFunc},
  {path: '/proc', name: 'proc', component: SystemProc},
  {path: '/proc/:func', name: 'proc', component: SystemProc},
  {path: '/iframe/:menuId/:loginUid', name: 'iframe', component: MkIframe},
  {path: '/iframe/:menuId/:loginUid/:bid', name: 'iframe', component: MkIframe},
  {path: '/view/:menuId', name: 'iframe', component: MkIframe},
  {path: '/view/:menuId/:bid', name: 'iframe', component: MkIframe},
  {path: '/interface', name: 'interface', component: Interface}
  {path: '/login', name: 'login', component: Login}
]
export default class RouteConfig extends Component {
src/views/login/index.jsx
@@ -1,52 +1,14 @@
import React, { Component } from 'react'
import { message, Modal } from 'antd'
import md5 from 'md5'
import moment from 'moment'
import Api from '@/api'
import Utils from '@/utils/utils.js'
import MKEmitter from '@/utils/events.js'
import { styles } from '@/store/options.js'
import zhCN from '@/locales/zh-CN/login.js'
import enUS from '@/locales/en-US/login.js'
import asyncComponent from '@/utils/asyncComponent'
import asyncLoadComponent from '@/utils/asyncLoadComponent'
import './index.scss'
const LoginForm = asyncLoadComponent(() => import('./loginform'))
const Resetpwd = asyncLoadComponent(() => import('@/components/resetPassword'))
const LoginCloudForm = asyncComponent(() => import('./logincloudform'))
const iszhCN = sessionStorage.getItem('lang') !== 'en-US'
const _href = window.location.href.split('#')[0]
class Login extends Component {
  state = {
    selectedlang: iszhCN ? 'zh-CN' : 'en-US',
    dict: iszhCN ? zhCN : enUS,
    isDisabled: false,
    auth: false,
    authError: '',
    loginlogo: window.GLOB.loginlogo || '',
    bgImage: window.GLOB.bgImage || '',
    platName: window.GLOB.platName || '',
    copyRight: window.GLOB.copyRight || '',
    ICP: window.GLOB.ICP || '',
    lineColor: window.GLOB.lineColor || '',
    webSite: window.GLOB.webSite || '',
    langList: [],
    syncApp: false,
    loginWays: null,
    touristLogin: false,
    syncing: false,
  }
  changelang (item) {
    // 切换语言
    this.setState({
      dict: item === 'zh-CN' ? zhCN : enUS
    })
  }
  state = {}
  handleSubmit = () => {
    this.loginformRef.handleConfirm().then(res => {
@@ -54,11 +16,7 @@
        isDisabled: true
      })
      if (res.type === 'uname_pwd') {
        this.loginsubmit(res)
      } else if (res.type === 'sms_vcode') {
        this.phoneloginsubmit(res)
      }
      this.loginsubmit(res)
    })
  }
@@ -70,176 +28,12 @@
    // 登录提交
    let res = await Api.getusermsg(param.username, param.password, false)
    if (res.status) {
      if (res.check_mob) {
        let loginWays = this.state.loginWays.filter(item => item.type === 'sms_vcode')
        if (loginWays.length > 0) {
          this.setState({loginWays: null, isDisabled: false}, () => {
            this.setState({loginWays: loginWays})
          })
          Modal.warning({
            title: '为确认是您本人操作,请使用手机短信验证码进行身份认证',
            okText: '知道了'
          })
          return
        }
      }
      sessionStorage.setItem('UserID', res.UserID)
      sessionStorage.setItem('LoginUID', res.LoginUID)
      sessionStorage.setItem('User_Name', res.UserName)
      sessionStorage.setItem('Full_Name', res.FullName)
      sessionStorage.setItem('avatar', res.icon || '')
      sessionStorage.setItem('dataM', res.dataM ? 'true' : '')
      sessionStorage.setItem('debug', res.debug || '')
      sessionStorage.setItem('role_id', res.role_id || '')
      sessionStorage.setItem('departmentcode', res.departmentcode || '')
      sessionStorage.setItem('organization', res.organization || '')
      sessionStorage.setItem('mk_user_type', res.mk_user_type || '')
      if (res.paas_externalDatabase) {
        sessionStorage.setItem('externalDatabase', res.paas_externalDatabase)
        window.GLOB.externalDatabase = `[${res.paas_externalDatabase}]..`
      }
      localStorage.setItem(_href + 'lang', param.lang || 'zh-CN')
      sessionStorage.setItem('lang', param.lang || 'zh-CN')
      sessionStorage.removeItem('visitorUserID')
      sessionStorage.removeItem('visitorLoginUID')
      let users = localStorage.getItem(_href + 'users')
      if (users) {
        try {
          users = JSON.parse(window.decodeURIComponent(window.atob(users)))
        } catch (e) {
          console.warn('Parse Failure')
          users = []
        }
      } else {
        users = []
      }
      users = users.filter(item => item.username !== param.username)
      if (users.length > 4) {
        users.length = 4
      }
      users.unshift({username: param.username, password: param.remember ? param.password : ''})
      localStorage.setItem(_href + 'users', window.btoa(window.encodeURIComponent(JSON.stringify(users))))
      let level = localStorage.getItem(_href + 'pwdlevel')
      if (level && process.env.NODE_ENV === 'production') {
        let visible = false
        let tip = '密码强度不够,请修改密码!'
        if (param.password.length < 8) {
          visible = true
        } else if (level === 'letter_num' && /^([^0-9]*|[^a-zA-Z]*)$/.test(param.password)) {
          visible = true
        } else if ((level === 'char_num' || level === 'char_num_90' || level === 'char_num_90_sms') && /^([^0-9]*|[^a-zA-Z]*|[^!@#$%^&*()_]*)$/.test(param.password)) {
          visible = true
        } else if ((level === 'char_num_90' || level === 'char_num_90_sms') && res.modifydate) {
          let s = (new Date().getTime() - new Date(res.modifydate).getTime()) / (1000 * 24 * 60 * 60)
          if (!isNaN(s) && s > 90) {
            visible = true
            tip = '您已90天未修改密码,请更换密码后使用!'
          }
        }
        if (visible) {
          message.warning(tip)
          this.setState({
            isDisabled: false
          })
          MKEmitter.emit('resetpassword', () => {
            const input = document.getElementById('password')
            if (input) {
              input.select()
            }
          })
          return
        }
      }
      let iframe = sessionStorage.getItem('iframe')
      if (iframe) {
        sessionStorage.removeItem('iframe')
        this.props.history.replace(iframe.replace(/@loginuid@/, res.LoginUID))
      } else {
        this.props.history.replace('/main')
      }
    } else if (res.ErrCode === 'Need_Get_Appkey' && window.GLOB.sysType === 'SSO') {
      message.warning('应用尚未创建,请向云端同步应用!')
      this.setState({
        isDisabled: false,
        syncApp: true
      Modal.warning({
        title: '登录成功!',
        okText: '知道了'
      })
    } else {
      message.warning(res.message)
      if (res.message.indexOf('密码错误') > -1) {
        const input = document.getElementById('password')
        if (input) {
          input.select()
        }
      } else if (res.message.indexOf('登录权限') > -1) {
        const wrap = document.getElementById('username')
        const input = wrap ? wrap.getElementsByTagName('input')[0] : null
        if (input) {
          input.select()
        }
      }
      this.setState({
        isDisabled: false
      })
    }
  }
  async phoneloginsubmit (param) {
    // 登录提交
    let res = await Api.getphoneusermsg(param.phone, param.vercode, false)
    if (res.status) {
      sessionStorage.setItem('UserID', res.UserID)
      sessionStorage.setItem('LoginUID', res.LoginUID)
      sessionStorage.setItem('User_Name', res.UserName)
      sessionStorage.setItem('Full_Name', res.FullName)
      sessionStorage.setItem('avatar', res.icon || '')
      sessionStorage.setItem('dataM', res.dataM ? 'true' : '')
      sessionStorage.setItem('debug', res.debug || '')
      sessionStorage.setItem('role_id', res.role_id || '')
      sessionStorage.setItem('departmentcode', res.departmentcode || '')
      sessionStorage.setItem('organization', res.organization || '')
      sessionStorage.setItem('mk_user_type', res.mk_user_type || '')
      if (res.paas_externalDatabase) {
        sessionStorage.setItem('externalDatabase', res.paas_externalDatabase)
        window.GLOB.externalDatabase = `[${res.paas_externalDatabase}]..`
      }
      localStorage.setItem(_href + 'lang', param.lang || 'zh-CN')
      sessionStorage.setItem('lang', param.lang || 'zh-CN')
      sessionStorage.removeItem('visitorUserID')
      sessionStorage.removeItem('visitorLoginUID')
      let iframe = sessionStorage.getItem('iframe')
      if (iframe) {
        sessionStorage.removeItem('iframe')
        this.props.history.replace(iframe.replace(/@loginuid@/, res.LoginUID))
      } else {
        this.props.history.replace('/main')
      }
    } else if (res.ErrCode === 'Need_Get_Appkey' && window.GLOB.sysType === 'SSO') {
      message.warning('应用尚未创建,请向云端同步应用!')
      this.setState({
        isDisabled: false,
        syncApp: true
      })
    } else {
      message.warning(res.message)
@@ -247,609 +41,6 @@
        isDisabled: false
      })
    }
  }
  authLogin = (appid, openid, memberid, scanId) => {
    Api.getTouristMsg('mk', appid, openid, memberid, scanId).then(res => {
      if (res.status) {
        sessionStorage.setItem('UserID', res.UserID)
        sessionStorage.setItem('LoginUID', res.LoginUID)
        sessionStorage.setItem('User_Name', res.UserName)
        sessionStorage.setItem('Full_Name', res.FullName)
        sessionStorage.setItem('avatar', res.icon || '')
        sessionStorage.setItem('dataM', res.dataM ? 'true' : '')
        sessionStorage.setItem('debug', res.debug || '')
        sessionStorage.setItem('role_id', res.role_id || '')
        sessionStorage.setItem('departmentcode', res.departmentcode || '')
        sessionStorage.setItem('organization', res.organization || '')
        sessionStorage.setItem('mk_user_type', res.mk_user_type || '')
        if (res.paas_externalDatabase) {
          sessionStorage.setItem('externalDatabase', res.paas_externalDatabase)
          window.GLOB.externalDatabase = `[${res.paas_externalDatabase}]..`
        }
        sessionStorage.removeItem('visitorUserID')
        sessionStorage.removeItem('visitorLoginUID')
        let iframe = sessionStorage.getItem('iframe')
        if (iframe) {
          sessionStorage.removeItem('iframe')
          this.props.history.replace(iframe.replace(/@loginuid@/, res.LoginUID))
        } else {
          this.props.history.replace('/main')
        }
      } else if (res.ErrCode === 'Need_Get_Appkey' && window.GLOB.sysType === 'SSO') {
        message.warning('应用尚未创建,请向云端同步应用!')
        this.setState({
          isDisabled: false,
          syncApp: true
        })
      } else {
        message.warning(res.message)
        this.setState({
          isDisabled: false
        })
      }
    })
  }
  jsonp(url) {
    return new Promise((resolve, reject) => {
      window.jsonCallBack = (result) => {
        resolve(result)
      }
      const JSONP = document.createElement('script')
      JSONP.type = 'text/javascript'
      JSONP.src = url
      document.getElementsByTagName('head')[0].appendChild(JSONP)
      setTimeout(() => {
        document.getElementsByTagName('head')[0].removeChild(JSONP)
      },500)
    })
  }
  componentDidMount () {
    // md5("/ws/location/v1/ip?callback=callbackFunction&key=key&output=jsonp secret key")
    // md5("/ws/location/v1/ip?callback=callbackFunction&key=BA7BZ-4QB65-LFCIA-QPDA6-4G6O7-MJB4Q&output=jsonpuThL4ZM3XOj642ksEQh76tyHFjh4")
    setTimeout(() => {
      Api.delCacheConfig()
    }, 50)
    if (window.GLOB.filter) {
      let view = document.getElementById('mk-login-view')
      if (view) {
        view.style.filter = 'grayscale(100%)'
      }
    }
    const _addressUrl = _href + 'queryAddress'
    if (localStorage.getItem(_addressUrl) === 'true') {
      this.queryAddress()
    }
    const timeStamp = new Date().getTime()
    const _authUrl = _href + 'AuthCode'
    let authCode = localStorage.getItem(_authUrl)
    let _s = md5('mksoft' + moment().format('YYYYMMDD'))
    authCode = authCode ? authCode.split(',') : []
    let index = authCode.findIndex(key => key === _s)
    let license = false
    if (window.GLOB.licenseKey) {
      if (window.GLOB.licenseKey.length !== 20) {
        Modal.warning({
          title: `本地授权码已失效,请联系管理员。`,
          okText: '知道了'
        })
      } else {
        let key = md5(window.GLOB.appId + 'minke_software' + window.GLOB.appkey).toUpperCase().substr(-6)
        let key1 = window.GLOB.licenseKey.substring(0, 6)
        let key2 = window.GLOB.licenseKey.substring(6, 14)
        let key3 = window.GLOB.licenseKey.substring(14)
        let key4 = md5(key1 + key2).toUpperCase().substr(-6)
        if (key === key1 && key3 === key4) {
          let last = window.GLOB.appkey[window.GLOB.appkey.length - 1]
          let offset = 0
          let keys = {}
          if (!isNaN(+last)) {
            offset = (10 - last) % 10
          } else {
            last = last.charCodeAt() - 65
            offset = (30 - last) % 10
          }
          for (let i = 0; i < 26; i++) {
            let char = String.fromCharCode(65 + i)
            keys[char] = (offset + i) % 10
          }
          let lictime = key2.replace(/[A-Z]/ig, (s) => {
            return keys[s]
          })
          lictime = lictime.slice(0,4) + '/' + lictime.slice(4,6) + '/' + lictime.slice(6)
          lictime = Math.floor(new Date(lictime).getTime() / 86400000)
          let curtime = Math.floor(new Date().getTime() / 86400000)
          let licday = lictime - curtime
          let _mindUrl = _href + 'notMind'
          if (licday < 0 || isNaN(licday)) {
            Modal.warning({
              title: '本地授权码已失效,请联系管理员。',
              okText: '知道了'
            })
          } else if (licday > 20) {
            license = true
            localStorage.removeItem(_mindUrl)
          } else {
            license = true
            if (localStorage.getItem(_mindUrl) !== 'false') {
              Modal.confirm({
                title: `距离授权到期还剩${licday}天,请联系管理员。`,
                okText: '不在提醒',
                cancelText: '关闭',
                onOk() {
                  localStorage.setItem(_mindUrl, 'false')
                },
                onCancel() {},
              })
            }
          }
        } else {
          Modal.warning({
            title: '本地授权码已失效,请联系管理员。',
            okText: '知道了'
          })
        }
      }
    }
    if ((!window.GLOB.licenseKey && index > -1) || license) {
      this.setState({
        auth: true
      })
    }
    if (!window.GLOB.licenseKey && (index === -1 || index > 5)) {
      let str = md5('MK19' + window.GLOB.appId + timeStamp)
      let _rduri = window.atob('aHR0cHM6Ly9lcGMubWs5aC5$mkjbi93ZWJhcGkvZG9zdGFycw=='.replace(/\$mk/ig, ''))
      let _func = window.atob('c0VtcG93ZXJDbG91$mkZF9HZXRfTGlua1VybA=='.replace(/\$mk/ig, ''))
      let _id = window.atob('YmgwYmFwYWJ0ZDQ1ZXBz$mkZ3JhNzlzZWdiY2g2YzFpYms='.replace(/\$mk/ig, ''))
      let param = {
        func: _func,
        AppID: window.GLOB.appId,
        TimeStamp: timeStamp,
        appkey: window.GLOB.appkey,
        SessionUid: localStorage.getItem('SessionUid') || '',
        userid: _id,
        LoginUID: _id,
        nonc: Utils.getuuid()
      }
      // param = {
      //   func: _func,
      //   VerificationCode: '授权码',
      //   TimeStamp: timeStamp,
      //   userid: _id,
      //   LoginUID: _id,
      //   nonc: Utils.getuuid()
      // }
      let keys = Object.keys(param).sort()
      let values = ''
      keys.forEach(key => {
        values += key + param[key]
      })
      param.sign = md5(values)
      param.t = new Date().getTime()
      Api.directRequest({
        url: _rduri + '/' + _func,
        method: 'post',
        data: JSON.stringify(param)
      }).then(res => {
        if (res.status) {
          if (res.EPC === str) {
            let box = []
            for (let i = 0; i < 15; i++) {
              let s = 'mksoft' + moment().add(i, 'days').format('YYYYMMDD')
              box.push(md5(s))
            }
            box = box.join(',')
            localStorage.setItem(_authUrl, box)
            this.setState({
              auth: true
            })
            if (res.warning_day && res.warning_day < 20) {
              Modal.warning({
                title: `距离授权到期还剩${res.warning_day}天,请联系管理员。`,
                okText: '知道了'
              })
            }
          } else {
            localStorage.removeItem(_authUrl)
            this.setState({
              auth: false
            })
          }
          if (res.query_address !== 'true') {
            localStorage.setItem(_addressUrl, 'false')
          } else {
            localStorage.setItem(_addressUrl, 'true')
            this.queryAddress()
          }
        } else if (res.ErrCode === 'N') {
          localStorage.removeItem(_authUrl)
          this.setState({
            auth: false,
            authError: res.message
          })
        }
      }, (error) => {
        if (error && error.ErrCode === 'LoginError') {
          let param = {
            func: 's_visitor_login',
            timestamp: moment().format('YYYY-MM-DD HH:mm:ss'),
            SessionUid: _id,
            TypeCharOne: 'pc',
            appkey: '202004041613277377A6A2456D34A4948AE84'
          }
          param.LText = md5(window.btoa(_id + param.timestamp))
          param.secretkey = md5(param.LText + 'mingke' + param.timestamp)
          let params = {
            url: _rduri.replace('dostars', 'dologon'),
            method: 'post',
            data: JSON.stringify(param)
          }
          Api.directRequest(params)
          return
        }
        if (index === -1 || index > 10) {
          this.setState({
            auth: false,
            authError: '网络错误导致系统授权失败,请联系管理员。'
          })
        }
      })
    }
    Api.getTouristMsg().then(result => {
      if (result.status) {
        // if (result.website && process.env.NODE_ENV === 'production') {
        //   let website = result.website.replace(/http(s)?:\/\/|\/$/ig, '').toLowerCase()
        //   let current = window.GLOB.baseurl.replace(/http(s)?:\/\/|\/$/ig, '').toLowerCase()
        //   if (website !== current) {
        //     try {
        //       window.history.replaceState(null, null, result.website.replace(/\/$/ig, '') + '/admin/index.html#/login')
        //       window.location.reload()
        //     } catch(e) {
        //       window.location.href = result.website.replace(/\/$/ig, '') + '/admin/index.html#/login'
        //     }
        //     return
        //   }
        // }
        sessionStorage.setItem('visitorUserID', result.UserID || '')
        sessionStorage.setItem('visitorLoginUID', result.LoginUID || '')
        if (result.UserID && result.LoginUID) {
          this.setState({touristLogin: true})
        }
        // 获取系统信息
        let _param = {
          func: 's_Get_style',
          TypeCharOne: 'PC',
          LText: `select '${window.GLOB.appkey}'`,
        }
        _param.userid = result.UserID
        _param.LoginUID = result.LoginUID
        _param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
        _param.secretkey = Utils.encrypt(_param.LText, _param.timestamp)
        Api.getSystemConfig(_param).then(res => {
          if (!res) return
          if (res.status) {
            if (window.GLOB.sysType === 'local' && window.GLOB.systemType !== 'production') {
              if (md5(('mk' + window.GLOB.appkey + res.sys_datetime + res.member_type + res.registry_date).toLowerCase()) !== res.secret_key) {
                Modal.warning({
                  title: '密钥错误,请联系管理员!',
                  okText: '知道了'
                })
                this.setState({
                  auth: false,
                  authError: '密钥错误,请联系管理员!'
                })
                return
              } else if (res.member_type === 'personal' && res.registry_date) {
                let saveDelay = 0
                try {
                  saveDelay = parseInt((new Date().getTime() - new Date(res.registry_date).getTime()) / 4320000)
                  sessionStorage.setItem('mkDelay', saveDelay)
                } catch(e) {}
              }
            }
            if (!['shutter', 'linkage_navigation', 'linkage', 'menu_board', 'menu_board_navigation'].includes(res.menu_type)) {
              res.menu_type = 'shutter'
            }
            let _url = _href + 'system'
            let systemMsg = {
              favicon: res.titlelogo || '',
              platTitle: res.titleName || '',
              platName: res.SysName || '',
              bgImage: res.Banner || '',
              loginlogo: res.loginlogo || '',
              copyRight: res.CopyRightYear && res.CopyRightOrg ? `Copyright©${res.CopyRightYear}    所有相关版权归    ${res.CopyRightOrg}` : '',
              ICP: res.ICP || '',
              mainlogo: res.indexlogo || '',
              doclogo: res.doclogo || '',
              style: res.CSS || '',
              showline: res.split_line_show || 'true',
              webSite: res.WebSite || '',
              navBar: res.menu_type, // shutter 百叶窗、linkage_navigation 联动菜单、linkage 联动菜单_无导航栏、menu_board 菜单面板、menu_board_navigation 菜单面板_标签页
              app_version: res.app_version,
              Member_Level: 0,
              appname: res.appname || ''
            }
            if ([10, 20, 30, 40, 50, 60, 70, 80, 90, 100].includes(res.member_level)) {
              systemMsg.Member_Level = md5('mksoft' + window.GLOB.appkey + res.member_level)
              if (!window.GLOB.memberLevel) {
                Object.defineProperty(window.GLOB, 'memberLevel', {
                  writable: false,
                  value: res.member_level
                })
              }
            }
            let level = res.pwd_level || ''
            if (level && !['letter_num', 'char_num', 'char_num_90', 'char_num_90_sms'].includes(level)) {
              level = ''
            }
            localStorage.setItem(_href + 'pwdlevel', level)
            if (res.srcid) {
              localStorage.setItem(_href + 'srcId', res.srcid)
            } else {
              localStorage.removeItem(_href + 'srcId')
            }
            sessionStorage.setItem('home_background', res.index_background_color || '')
            let seconds = 0
            if (res.sys_datetime) {
              seconds = Math.floor((new Date(res.sys_datetime).getTime() - new Date().getTime()) / 1000)
            }
            sessionStorage.setItem('sys_time_shim', isNaN(seconds) ? 0 : seconds)
            // url标题
            document.title = systemMsg.platTitle
            try {
              localStorage.setItem(_url, window.btoa(window.encodeURIComponent(JSON.stringify(systemMsg))))
            } catch (e) {
              localStorage.removeItem(_url)
            }
            let _loginurl = _href + 'loginways'
            let login_ways = []
            let login_types = []
            if (res.login_ways && res.login_ways.length > 0) {
              res.login_ways.forEach(item => {
                // 短信验证码登录,必须设置短信Id
                if (item.way_no === 'sms_vcode' && !item.sms_id) return
                if (login_types.includes(item.way_no)) return
                login_types.push(item.way_no)
                login_ways.push({
                  type: item.way_no,
                  smsId: item.sms_id
                })
                if (item.way_no === 'sms_vcode' && item.sms_id) {
                  sessionStorage.setItem('mk_sms_id', item.sms_id)
                }
              })
            } else {
              login_ways.push({
                type: 'uname_pwd',
                smsId: ''
              })
            }
            try {
              localStorage.setItem(_loginurl, window.btoa(window.encodeURIComponent(JSON.stringify(login_ways))))
            } catch (e) {
              localStorage.removeItem(_loginurl)
            }
            this.setState({
              loginWays: login_ways,
              langList: res.lang_data || [],
              ...systemMsg
            })
            window.GLOB.mainlogo = systemMsg.mainlogo
            window.GLOB.style = systemMsg.style
            window.GLOB.navBar = systemMsg.navBar
            window.GLOB.appVersion = systemMsg.app_version
            sessionStorage.setItem('appname', res.appname || '')
            if (window.GLOB.style && styles[window.GLOB.style]) {
              document.body.className = styles[window.GLOB.style] + ' ' + (res.split_line_show === 'false' ? 'hidden-split-line' : '')
            }
            if (res.titlelogo && window.GLOB.favicon !== res.titlelogo) {
              let link = document.querySelector("link[rel*='icon']") || document.createElement('link')
              link.type = 'image/x-icon'
              link.rel = 'shortcut icon'
              link.href = res.titlelogo
              document.getElementsByTagName('head')[0].appendChild(link)
            }
            // positecgroup
            // if (res.users_upt === 'true' && window.GLOB.systemType === 'production') {
            //   Api.genericInterface ({
            //     func: 's_Get_local_u_deleted',
            //     users_upt_date: res.users_upt_date,
            //     userid: result.UserID,
            //     LoginUID: result.LoginUID
            //   }).then(localres => {
            //     if (!localres.status) return
            //     Api.getSystemConfig({
            //       func: 's_get_sso_u_create',
            //       user_ids: localres.user_ids,
            //       user_ids_local: localres.user_ids_local,
            //       users_upt_date: localres.users_upt_date,
            //       userid: result.UserID,
            //       LoginUID: result.LoginUID
            //     }).then(ssores => {
            //       if (!ssores.status) return
            //       Api.genericInterface ({
            //         func: 's_get_local_u_create',
            //         user_ids_local: ssores.user_ids_local,
            //         userid: result.UserID,
            //         LoginUID: result.LoginUID
            //       })
            //     })
            //   })
            // }
          } else {
            message.warning(res.message)
          }
        })
      } else {
        message.warning(result.message)
      }
    })
    let loginWays = localStorage.getItem(_href + 'loginways')
    if (loginWays) {
      try {
        loginWays = JSON.parse(window.decodeURIComponent(window.atob(loginWays)))
      } catch (e) {
        loginWays = null
      }
      this.setState({
        loginWays: loginWays
      })
    }
  }
  queryAddress = () => {
    window.callbackFunction = (res) => {
      if (res.result && res.result.ad_info) {
        sessionStorage.setItem('nation', res.result.ad_info.nation || '')
        sessionStorage.setItem('province', res.result.ad_info.province || '')
        sessionStorage.setItem('city', res.result.ad_info.city || '')
        sessionStorage.setItem('district', res.result.ad_info.district || '')
        sessionStorage.setItem('address', res.result.ad_info.address || '')
        sessionStorage.setItem('ipAddress', res.result.ip || '')
      }
    }
    const JSONP = document.createElement('script')
    JSONP.type = 'text/javascript'
    JSONP.src = 'https://apis.map.qq.com/ws/location/v1/ip?callback=callbackFunction&key=BA7BZ-4QB65-LFCIA-QPDA6-4G6O7-MJB4Q&output=jsonp&sig=3e5ebecb324ba266bf80014dcc8380db'
    document.getElementsByTagName('head')[0].appendChild(JSONP)
    setTimeout(() => {
      document.getElementsByTagName('head')[0].removeChild(JSONP)
    },500)
  }
  syncSubmit = () => {
    this.setState({
      syncing: true
    })
    let param = {
      func: 's_get_app_from_cloud',
      UserName: '',
      Password: '',
      systemType: window.GLOB.sysType,
      Type: 'X',
      debug: 'Y'
    }
    param.appkey = window.GLOB.appkey || ''
    if (window.GLOB.cloudServiceApi) {
      param.rduri = window.GLOB.cloudServiceApi.replace('dostars', 'dostar')
    }
    this.logincloudRef.handleConfirm().then(result => {
      param.UserName = result.cloudusername
      param.Password = result.cloudpassword
      param.Password = Utils.formatOptions(param.Password)
      Api.dostarInterface(param).then(res => {
        if (res.status) {
          let _param = {
            func: 's_sDataDictb_TBBack',
            LTextOut: res.LTextOut,
            lid: res.Lid,
            Appkey: window.GLOB.appkey || ''
          }
          _param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
          _param.secretkey = Utils.encrypt(_param.LTextOut, _param.timestamp)
          _param.open_key = Utils.encryptOpenKey(_param.secretkey, _param.timestamp)
          Api.dostarInterface(_param).then(response => {
            if (response.status) {
              message.success('应用创建成功。')
              this.setState({
                syncing: false,
                syncApp: false
              })
            } else {
              this.setState({
                syncing: false
              })
              message.warning(response.message)
            }
          })
        } else {
          this.setState({
            syncing: false
          })
          message.warning(res.message)
        }
      })
    })
  }
  /**
@@ -862,55 +53,23 @@
  }
  render () {
    const { lineColor, bgImage, loginlogo, copyRight, webSite, ICP, loginWays, touristLogin } = this.state
    return (
      <div className="login-container" id="mk-login-view" style={bgImage ? {backgroundImage: 'url(' + bgImage + ')'} : {}}>
        <div className="logo" style={lineColor ? {borderColor: lineColor} : {}}>
          {loginlogo ? <img src={loginlogo} alt=""/> : null}
          {this.state.platName ? <p className="plat-name">{this.state.platName}</p> : null}
      <div className="login-container" style={{backgroundImage: 'url(http://cloud.mk9h.cn/Content/images/upload/2020-03-26/2020032618034533512354_loginbg.ae892b3f.jpg)'}}>
        <div className="logo">
          <img src="http://cloud.mk9h.cn/Content/images/upload/2020-03-26/2020032615130529681770_login-logo.a638e393.png" alt=""/>
          <p className="plat-name">明科商业智能开放平台</p>
        </div>
        <div className="login-middle" style={lineColor ? {borderColor: lineColor} : {}}>
          {loginWays ? <LoginForm
            dict={this.state.dict}
            auth={this.state.auth}
            authError={this.state.authError}
            touristLogin={touristLogin}
            loginWays={loginWays}
            lang={this.state.selectedlang}
            langList={this.state.langList}
        <div className="login-middle">
          <LoginForm
            isDisabled={this.state.isDisabled}
            changelang={(value) => this.changelang(value)}
            handleSubmit={() => this.handleSubmit()}
            authLogin={this.authLogin}
            wrappedComponentRef={(inst) => this.loginformRef = inst}
          /> : null}
          />
        </div>
        <div className="login-bottom">
          {webSite && copyRight ?
            <a target="_blank" rel="noopener noreferrer" href={webSite} dangerouslySetInnerHTML={{ __html: copyRight.replace(/\s/ig, '&nbsp;') }}></a> :
            <p dangerouslySetInnerHTML={{ __html: copyRight ? copyRight.replace(/\s/ig, '&nbsp;') : '' }}></p>
          }
          {ICP ? <a target="_blank" rel="noopener noreferrer" href="https://beian.miit.gov.cn/#/Integrated/index" dangerouslySetInnerHTML={{ __html: ICP.replace(/\s/ig, '&nbsp;') }}></a> : null}
          <p>Copyright©2020    所有相关版权归    北京明科普华信息技术有限公司</p>
          <a target="_blank" rel="noopener noreferrer" href="https://beian.miit.gov.cn/#/Integrated/index">京ICP备12007830号</a>
        </div>
        {/* 编辑状态登录 */}
        <Modal
          title={this.state.dict['login.sync.cloud']}
          okText={this.state.dict['login.ok']}
          cancelText={this.state.dict['login.cancel']}
          visible={this.state.syncApp}
          onOk={this.syncSubmit}
          maskClosable={false}
          className="sync-cloud-application"
          width={'430px'}
          confirmLoading={this.state.syncing}
          onCancel={() => {this.setState({ syncApp: false, syncing: false })}}
          destroyOnClose
        >
          <LoginCloudForm handleSubmit={() => this.syncSubmit()} wrappedComponentRef={(inst) => this.logincloudRef = inst}/>
        </Modal>
        {/* 修改密码 */}
        <Resetpwd />
      </div>
    )
  }
src/views/login/logincloudform.jsx
File was deleted
src/views/login/loginform.jsx
@@ -1,156 +1,22 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import { Form, Input, Button, Checkbox, Select, Modal, message, AutoComplete } from 'antd'
import { UserOutlined, LockOutlined, QrcodeOutlined, RedoOutlined, CloseCircleOutlined } from '@ant-design/icons'
import md5 from 'md5'
import moment from 'moment'
import { Form, Input, Button, Checkbox } from 'antd'
import { UserOutlined, LockOutlined } from '@ant-design/icons'
import Api from '@/api'
import Utils from '@/utils/utils.js'
import options from '@/store/options.js'
import asyncLoadComponent from '@/utils/asyncLoadComponent'
import zhCN from '@/locales/zh-CN/login.js'
import './index.scss'
const { warning } = Modal
let LoginVerCodeTimer = null
const QrCode = asyncLoadComponent(() => import('@/components/qrcode'))
class LoginTabForm extends Component {
  static propTpyes = {
    isDisabled: PropTypes.bool,
    changelang: PropTypes.func,
    handleSubmit: PropTypes.func,
    authLogin: PropTypes.func,
    dict: PropTypes.object,
    auth: PropTypes.bool,
    authError: PropTypes.string,
    touristLogin: PropTypes.bool,
    lang: PropTypes.string,
    langList: PropTypes.array,
    loginWays: PropTypes.array
    handleSubmit: PropTypes.func
  }
  state = {
    activeKey: 'uname_pwd',
    scanId: '',
    dict: zhCN,
    username: '',
    password: '',
    remember: true,
    delay: null,
    loginWays: [],
    smsId: '',
    verdisabled: false,
    hasScan: false,
    timeout: false,
    users: []
  }
  timer = null
  splitTime = 0
  UNSAFE_componentWillMount () {
    const { loginWays } = this.props
    let remember = true
    let _url = window.location.href.split('#')[0]
    if (localStorage.getItem(_url + 'remember') === 'false') {
      remember = false
    }
    if (!window.GLOB.keepKey) {
      remember = false
    }
    let smsId = ''
    let hasScan = false
    let _loginWays = []
    loginWays.forEach(item => {
      if (item.type === 'sms_vcode') {
        item.label = '短信登录'
        smsId = item.smsId
        _loginWays.push(item)
      } else if (item.type === 'uname_pwd') {
        item.label = '账号登录'
        _loginWays.push(item)
      } else if (item.type === 'app_scan') {
        _loginWays.push(item)
        hasScan = true
      }
    })
    let activeKey = _loginWays[0].type
    let users = localStorage.getItem(_url + 'users')
    let _user = null
    if (users) {
      try {
        users = JSON.parse(window.decodeURIComponent(window.atob(users)))
      } catch (e) {
        users = []
      }
    } else {
      users = []
    }
    if (users[0]) {
      _user = users[0]
    }
    this.setState({
      users: users,
      username: activeKey === 'uname_pwd' && _user ? _user.username : '',
      password: activeKey === 'uname_pwd' && _user ? _user.password : '',
      smsId: smsId,
      loginWays: _loginWays,
      activeKey,
      scanId: activeKey === 'app_scan' ? Utils.getuuid() : '',
      timeout: false,
      remember,
      hasScan
    })
    if (activeKey === 'app_scan') {
      this.splitTime = 0
      this.timer = setTimeout(() => {
        this.checkResult()
      }, 10000)
    }
  }
  checkResult = () => {
    const { scanId } = this.state
    this.splitTime += 10000
    let _param = {
      func: 'webapi_get_binding_key',
      scan_type: 'pc',
      id: scanId,
      UserName: ''
    }
    _param.userid = sessionStorage.getItem('visitorUserID')
    _param.LoginUID = sessionStorage.getItem('visitorLoginUID')
    if (this.splitTime >= 180000) {
      this.setState({
        timeout: true
      })
      return
    }
    Api.getSystemConfig(_param).then(res => {
      if (!res.status) {
        message.warning(res.message)
        return
      } else if (res.thd_party_appid && res.thd_party_member_id && res.thd_party_openid) {
        this.props.authLogin(res.thd_party_appid, res.thd_party_openid, res.thd_party_member_id, scanId)
      } else {
        this.timer = setTimeout(() => {
          this.checkResult()
        }, 10000)
      }
    })
  }
  handleConfirm = () => {
@@ -159,13 +25,9 @@
    return new Promise((resolve, reject) => {
      this.props.form.validateFieldsAndScroll((err, values) => {
        if (!err) {
          if (activeKey === 'uname_pwd') {
            values.username = values.username.replace(/\t+|\v+|\s+/g, '')
            values.password = values.password.replace(/\t+|\v+|\s+/g, '')
          } else if (activeKey === 'sms_vcode') {
            values.phone = values.phone.replace(/\t+|\v+|\s+/g, '')
            values.vercode = values.vercode.replace(/\t+|\v+|\s+/g, '')
          }
          values.username = values.username.replace(/\t+|\v+|\s+/g, '')
          values.password = values.password.replace(/\t+|\v+|\s+/g, '')
          resolve({type: activeKey, ...values})
        } else {
          reject(err)
@@ -174,242 +36,30 @@
    })
  }
  changelang = (item) => {
    this.props.changelang(item)
  }
  handleSubmit = e => {
    const { activeKey } = this.state
    // 登录参数检验
    e && e.preventDefault()
    if (!this.props.auth) {
      warning({
        title: this.props.authError || this.props.dict['login.auth.tip'],
        okText: this.props.dict['login.ok'],
        cancelText: this.props.dict['login.cancel'],
        onOk() {},
        onCancel() {}
      })
      return
    }
    if (activeKey === 'uname_pwd') {
      if (!this.props.form.getFieldValue('username')) {
        const wrap = document.getElementById('username')
        const input = wrap ? wrap.getElementsByTagName('input')[0] : null
        if (input) {
          input.focus()
        }
      } else if (!this.props.form.getFieldValue('password')) {
        const input = document.getElementById('password')
        if (input) {
          input.focus()
        }
      } else {
        this.props.handleSubmit()
    if (!this.props.form.getFieldValue('username')) {
      const wrap = document.getElementById('username')
      if (wrap) {
        wrap.focus()
      }
    } else if (activeKey === 'sms_vcode') {
      if (!this.props.form.getFieldValue('phone')) {
        const input = document.getElementById('phone')
        if (input) {
          input.focus()
        }
      } else if (!this.props.form.getFieldValue('vercode')) {
        const input = document.getElementById('vercode')
        if (input) {
          input.focus()
        }
      } else {
        this.props.handleSubmit()
    } else if (!this.props.form.getFieldValue('password')) {
      const input = document.getElementById('password')
      if (input) {
        input.focus()
      }
    } else {
      this.props.handleSubmit()
    }
  }
  componentDidMount () {
    const wrap = document.getElementById('username')
    const input = wrap ? wrap.getElementsByTagName('input')[0] : null
    if (input) {
      input.focus()
    if (wrap) {
      wrap.focus()
    }
  }
  onChangeTab = (activeKey) => {
    this.setState({activeKey, scanId: activeKey === 'app_scan' ? Utils.getuuid() : ''})
    if (this.state.activeKey === 'app_scan') {
      this.timer && clearTimeout(this.timer)
    }
    if (activeKey === 'app_scan') {
      this.splitTime = 0
      this.setState({timeout: false})
      this.timer = setTimeout(() => {
        this.checkResult()
      }, 10000)
    }
  }
  reCode = () => {
    this.splitTime = 0
    this.setState({timeout: false, scanId: Utils.getuuid()})
    this.timer = setTimeout(() => {
      this.checkResult()
    }, 10000)
  }
  getvercode = () => {
    const { smsId } = this.state
    let _phone = this.props.form.getFieldValue('phone')
    if (!_phone) {
      message.warning('请输入手机号!')
      return
    } else if (!/^1[3456789]\d{9}$/.test(_phone)) {
      message.warning('手机号格式错误,请重填!')
      return
    } else if (!this.props.touristLogin) {
      message.warning('未获取验证码设置,请稍后或刷新重试!')
      return
    }
    let _param = {
      func: 'mes_sms_send_code_sso',
      send_type: 'login',
      mob: _phone,
      ID: smsId
    }
    _param.LText = 'minke'
    _param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
    _param.secretkey = md5(`${_param.LText}mingke${_param.timestamp}`)
    _param.userid = sessionStorage.getItem('visitorUserID') || ''
    _param.LoginUID = sessionStorage.getItem('visitorLoginUID') || ''
    Api.getSystemConfig(_param).then(res => {
      if (!res.status || !res.n_id) {
        message.warning(res.message || '验证码获取失败!')
        return
      }
      let param = {
        func: 'MSN_sms_send_code',
        send_type: 'login',
        mob: _phone,
        timestamp: moment().format('YYYY-MM-DD HH:mm:ss'),
        ID: smsId,
        n_id: res.n_id
      }
      param.LText = md5(`${_phone}mingke${window.GLOB.appkey}${param.timestamp}`)
      param.secretkey = md5(`${param.LText}mingke${param.timestamp}`)
      param.rduri = 'https://sso.mk9h.cn/webapi/dostars'
      param.userid = 'bh0bapabtd45epsgra79segbch6c1ibk'
      param.LoginUID = 'bh0bapabtd45epsgra79segbch6c1ibk'
      this.setState({
        verdisabled: true,
        delay: 60
      })
      LoginVerCodeTimer = setTimeout(this.resetVerCodeDelay, 1000)
      Api.genericInterface(param).then(res => {
        if (res.status) {
        } else {
          if (LoginVerCodeTimer) {
            clearTimeout(LoginVerCodeTimer)
          }
          this.setState({
            verdisabled: false,
            delay: null
          })
          message.warning(res.message)
        }
      }, (error) => {
        if (error && error.ErrCode === 'LoginError') {
          let param = {
            func: 's_visitor_login',
            timestamp: moment().format('YYYY-MM-DD HH:mm:ss'),
            SessionUid: 'bh0bapabtd45epsgra79segbch6c1ibk',
            TypeCharOne: 'pc',
            appkey: '202004041613277377A6A2456D34A4948AE84'
          }
          param.LText = md5(window.btoa('bh0bapabtd45epsgra79segbch6c1ibk' + param.timestamp))
          param.secretkey = md5(param.LText + 'mingke' + param.timestamp)
          let params = {
            url: 'https://sso.mk9h.cn/webapi/dologon',
            method: 'post',
            data: JSON.stringify(param)
          }
          Api.directRequest(params)
          return
        }
        if (LoginVerCodeTimer) {
          clearTimeout(LoginVerCodeTimer)
        }
        this.setState({
          verdisabled: false,
          delay: null
        })
      })
    })
  }
  resetVerCodeDelay = () => {
    const { delay } = this.state
    if (delay && delay > 1) {
      this.setState({delay: delay - 1})
      LoginVerCodeTimer = setTimeout(this.resetVerCodeDelay, 1000)
    } else {
      this.setState({
        verdisabled: false,
        delay: null
      })
    }
  }
  rememberChange = (e) => {
    let val = e.target.checked
    let _url = window.location.href.split('#')[0]
    localStorage.setItem(_url + 'remember', val)
  }
  complete = (val) => {
    const { users } = this.state
    let user = users.filter(m => m.username === val)[0]
    let password = user && user.password ? user.password : ''
    this.props.form.setFieldsValue({password: password})
    if (!password) {
      const input = document.getElementById('password')
      if (input) {
        input.focus()
      }
    }
  }
  deleteUser = (e, val) => {
    const { users } = this.state
    e.stopPropagation()
    let _users = users.filter(m => m.username !== val)
    this.setState({users: _users})
    let _url = window.location.href.split('#')[0]
    localStorage.setItem(_url + 'users', window.btoa(window.encodeURIComponent(JSON.stringify(_users))))
  }
  /**
@@ -419,43 +69,26 @@
    this.setState = () => {
      return
    }
    this.timer && clearTimeout(this.timer)
  }
  render() {
    const { langList } = this.props
    const { getFieldDecorator } = this.props.form
    const { activeKey, verdisabled, delay, loginWays, remember, scanId, timeout, hasScan, users } = this.state
    const wayLabels = {app_scan: '扫码登录', uname_pwd: '账号登录', sms_vcode: '短信登录'}
    const { dict } = this.state
    return (
      <Form className="login-form" id="login-form" onSubmit={this.handleSubmit}>
        <div className="login-way-title">{wayLabels[activeKey]}</div>
        {hasScan && activeKey !== 'app_scan' ? <div className="scan-icon" onClick={() => this.onChangeTab('app_scan')}><QrcodeOutlined /></div> : null}
        {activeKey === 'uname_pwd' ? <div className="form-item-wrap">
        <div className="login-way-title">账号登录</div>
        <div className="form-item-wrap">
          <Form.Item>
            {getFieldDecorator('username', {
              rules: [{ required: true, message: this.props.dict['login.username.empty'] }],
              rules: [{ required: true, message: dict['login.username.empty'] }],
              initialValue: this.state.username || '',
            })(
              <AutoComplete
                className
                dataSource={users.map((cell, i) => <AutoComplete.Option className="mk-user-option" value={cell.username} key={i}>
                  {cell.username}
                  <CloseCircleOutlined onClick={(e) => this.deleteUser(e, cell.username)}/>
                </AutoComplete.Option>)}
                filterOption={false}
                onSelect={this.complete}
                defaultActiveFirstOption={false}
                defaultOpen={false}
                optionLabelProp="value"
              >
                <Input
                  prefix={<UserOutlined style={{ color: 'rgba(0,0,0,.25)' }} />}
                  placeholder={this.props.dict['login.username']}
                  autoComplete="off"
                />
              </AutoComplete>
              <Input
                prefix={<UserOutlined style={{ color: 'rgba(0,0,0,.25)' }} />}
                placeholder={dict['login.username']}
                autoComplete="off"
              />
            )}
          </Form.Item>
          <Form.Item>
@@ -464,115 +97,19 @@
              rules: [
                {
                  required: true,
                  message: this.props.dict['login.password.empty'],
                  message: dict['login.password.empty'],
                }
              ]
            })(<Input.Password placeholder={this.props.dict['login.password']} prefix={<LockOutlined style={{ color: 'rgba(0,0,0,.25)' }} />} />)}
            })(<Input.Password placeholder={dict['login.password']} prefix={<LockOutlined style={{ color: 'rgba(0,0,0,.25)' }} />} />)}
          </Form.Item>
          {window.GLOB.keepKey ? <Form.Item className="minline">
            {getFieldDecorator('remember', {
              valuePropName: 'checked',
              initialValue: remember,
            })(<Checkbox onChange={this.rememberChange}>{this.props.dict['login.remember']}</Checkbox>)}
          </Form.Item> : <div style={{height: '30px', float: 'left'}}></div>}
          {langList && langList.length > 0 ? <Form.Item className="minline right">
            {getFieldDecorator('lang', {
              initialValue: this.props.lang,
            })(
              <Select
                onChange={(value) => {this.changelang(value)}}
                getPopupContainer={() => document.getElementById('login-form')}
              >
                {langList.map((item, index) => {
                  return <Select.Option key={index} value={item.Lang}>{item.LangName}</Select.Option>
                })}
              </Select>
            )}
          </Form.Item> : null}
          <Form.Item className="minline">
            <Checkbox>{dict['login.remember']}</Checkbox>
          </Form.Item>
          <Form.Item className="btn-login">
            <Button type="primary" htmlType="submit" className="login-form-button" disabled={this.props.isDisabled} loading={this.props.isDisabled}>
              {this.props.dict['login.submit']}
              {dict['login.submit']}
            </Button>
          </Form.Item>
          {window.GLOB.sysType === 'cloud' && options.cdomain.indexOf('mk9h') > -1 ? <Form.Item className="register-line">
            <a href="http://www.minkesoft.com/signup" target="_blank" rel="noopener noreferrer" className="register">注册</a>
            <a href="http://www.minkesoft.com/forgotPwd" target="_blank" rel="noopener noreferrer" className="forgot">忘记密码?</a>
          </Form.Item> : null}
        </div> : null}
        {activeKey === 'sms_vcode' ? <div className="form-item-wrap">
          <Form.Item>
            {getFieldDecorator('phone', {
              rules: [{ required: true, message: this.props.dict['login.phone.empty'] }],
              initialValue: '',
            })(
              <Input
                placeholder={this.props.dict['login.phone']}
                autoComplete="off"
              />
            )}
          </Form.Item>
          <Form.Item className="vercode">
            {getFieldDecorator('vercode', {
              initialValue: '',
              rules: [
                {
                  required: true,
                  message: this.props.dict['login.vercode.empty'],
                }
              ]
            })(
              <Input
                addonAfter={
                  <Button type="link" className="vercode" size="small" disabled={verdisabled} onClick={this.getvercode}>
                    {delay ? `${delay}s后重新获取` : '获取验证码'}
                  </Button>
                }
                placeholder={this.props.dict['login.vercode']}
                autoComplete="off"
              />
            )}
          </Form.Item>
          {langList && langList.length > 0 ? <Form.Item className="minline right">
            {getFieldDecorator('lang', {
              initialValue: this.props.lang,
            })(
              <Select
                onChange={(value) => {this.changelang(value)}}
                getPopupContainer={() => document.getElementById('login-form')}
              >
                {langList.map((item, index) => {
                  return <Select.Option key={index} value={item.Lang}>{item.LangName}</Select.Option>
                })}
              </Select>
            )}
          </Form.Item> : null}
          <Form.Item className="btn-login">
            <Button type="primary" htmlType="submit" className="login-form-button" disabled={this.props.isDisabled} loading={this.props.isDisabled}>
              {this.props.dict['login.submit']}
            </Button>
          </Form.Item>
          {window.GLOB.sysType === 'cloud' && options.cdomain.indexOf('mk9h') > -1 ? <Form.Item className="register-line">
            <a href="http://www.minkesoft.com/signup" target="_blank" rel="noopener noreferrer" className="register">注册</a>
            <a href="http://www.minkesoft.com/forgotPwd" target="_blank" rel="noopener noreferrer" className="forgot">忘记密码?</a>
          </Form.Item> : null}
        </div> : null}
        {activeKey === 'app_scan' ? <div className="form-item-wrap">
          <div className="form-scan-wrap">
            <div className="qr-wrap">
              {scanId ? <QrCode card={{qrWidth: 500, color: '#000000'}} value={`mkpcscan,${window.GLOB.appkey},${scanId}`}/> : null}
              {timeout ? <div className="qrcode-out">
                <RedoOutlined onClick={this.reCode} />
                二维码已失效。
              </div> : null}
            </div>
            请使用客户端扫一扫登录
          </div>
        </div> : null}
        <div className={'login-ways ' + (activeKey === 'app_scan' ? 'center' : '')}>
          {loginWays.map(item => {
            if (item.type === 'app_scan' || activeKey === item.type) return null
            return (<span key={item.type} onClick={() => this.onChangeTab(item.type)}>{item.label}</span>)
          })}
        </div>
      </Form>
    )