king
2020-08-09 ce2b708f61de1855771d78f35309bd77df9d3b15
2020-08-09
25个文件已修改
2个文件已添加
737 ■■■■ 已修改文件
public/README.txt 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
public/options.json 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/index.js 230 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/header/index.jsx 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/index.js 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/mob/components/login/mob-login-2/index.jsx 290 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/mob/components/login/mob-login-2/index.scss 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/mob/contdelete/index.jsx 59 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/mob/contdelete/index.scss 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/mob/contupdate/index.jsx 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/mob/datasource/index.jsx 12 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/mob/datasource/index.scss 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/mob/datasource/verifycard/customscript/index.jsx 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/mob/datasource/verifycard/customscript/index.scss 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/commontable/index.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/formtab/index.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/subtable/index.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/subtabtable/index.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/treepage/index.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/actionList/normalbutton/index.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/actionList/printbutton/index.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/verifycard/index.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/treesettingcomponent/settingform/customscript/index.jsx 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/treesettingcomponent/settingform/customscript/index.scss 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/treesettingcomponent/settingform/index.jsx 22 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/treesettingcomponent/settingform/index.scss 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/login/index.jsx 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
public/README.txt
@@ -5,4 +5,5 @@
mainSystemApi -- sso系统的接口路径,注:业务系统需要填写,且值为通用接口的完整路径
systemType    -- 判断业务系统为测试 (空) 或正式 (production) ,正式系统开发权限只含有系统升级等限定功能
lineColor     -- 登录页分割线颜色
webStorage    -- 前端存储,使用时填入websql
filter        -- 页面滤镜,值为'true'时,页面显示为黑白色
public/options.json
@@ -4,5 +4,6 @@
  "mainSystemApi": "http://cloud.mk9h.cn/webapi/dostars",
  "systemType": "",
  "lineColor": "",
  "webStorage": "websql",
  "filter": "false"
}
src/api/index.js
@@ -6,6 +6,32 @@
import Utils from '@/utils/utils.js'
import options from '@/store/options.js'
let mkDB = null
if (window.GLOB.webSqlUsable) {
  let service = window.GLOB.service ? '-' + window.GLOB.service.replace('/', '') : ''
  try {
    mkDB = openDatabase(`mkdb${service}`, '1', 'mk-pc-database', 50 * 1024 * 1024)
    mkDB.transaction(tx => {
      tx.executeSql('CREATE TABLE IF NOT EXISTS VERSIONS (id unique, version varchar(50), CDefine1 varchar(50), CDefine2 varchar(50), CDefine3 varchar(50))', [], () => {
      }, () => {
        // eslint-disable-next-line
        throw 'CREATE TABLE ERROR'
      })
      tx.executeSql('CREATE TABLE IF NOT EXISTS CONFIGS (id unique, menuid varchar(50), userid varchar(50), openEdition varchar(50), webEdition varchar(50), LongParam text, LongParamUser text, CDefine1 varchar(50), CDefine2 varchar(50), CDefine3 varchar(50), CDefine4 varchar(50), CDefine5 varchar(50))', [], () => {
      }, () => {
        // eslint-disable-next-line
        throw 'CREATE TABLE ERROR'
      })
    })
  } catch (e) {
    console.warn(e)
    mkDB = null
  }
}
axios.defaults.crossDomain = true
axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded;charset=UTF-8'
axios.defaults.withCredentials = true
@@ -199,6 +225,82 @@
  }
  /**
   * @description 获取系统基本设置,启用或更新websql
   */
  getSystemStyle () {
    // 获取系统信息
    let param = {
      func: 's_Get_style',
      TypeCharOne: 'PC',
      LText: `select '${window.GLOB.appkey}'`,
    }
    param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss') + '.000'
    param.secretkey = Utils.encrypt(param.LText, param.timestamp)
    param.userid = sessionStorage.getItem('UserID') || ''
    param.lang = localStorage.getItem('lang') || ''
    param.SessionUid = localStorage.getItem('SessionUid') || ''
    param.LoginUID = sessionStorage.getItem('LoginUID') || ''
    param.appkey = window.GLOB.appkey || ''
    if (window.GLOB.mainSystemApi) {
      param.rduri = window.GLOB.mainSystemApi
    }
    param.nonc = Utils.getuuid()
    let keys = Object.keys(param).sort()
    let values = ''
    keys.forEach(key => {
      if (key === 'rduri' || key === 't') return
      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()
    return new Promise(resolve => {
      axios({
        url: `/webapi/dostars${param.func ? '/' + param.func : ''}`,
        data: param
      }).then(res => {
        if (mkDB) {
          let version = res.app_version ? `${res.app_version}` : '1'
          // mkDB.transaction(tx => {
          //   tx.executeSql('DROP TABLE CONFIGS')
          // })
          mkDB.transaction(tx => {
            tx.executeSql('SELECT * FROM VERSIONS', [], (tx, results) => {
              if (results.rows.length === 0) {
                tx.executeSql('INSERT INTO VERSIONS (id, version) VALUES (?, ?)', ['pc', version])
                tx.executeSql('DELETE FROM CONFIGS')
              } else if (results.rows.length === 1) {
                let _ver = results.rows[0]
                if (version !== _ver.version) {
                  tx.executeSql(`UPDATE VERSIONS SET version=${version}`)
                  tx.executeSql('DELETE FROM CONFIGS')
                }
              } else if (results.rows.length > 1) {
                tx.executeSql('DELETE FROM VERSIONS')
                tx.executeSql('INSERT INTO VERSIONS (id, version) VALUES (?, ?)', ['pc', version])
                tx.executeSql('DELETE FROM CONFIGS')
              }
            }, (tx, results) => {
              console.warn(results)
            })
          })
        }
        resolve(res)
      })
    })
  }
  /**
   * @description 获取或修改云端配置
   */
  getCloudConfig (param) {
@@ -311,6 +413,133 @@
  }
  /**
   * @description 获取系统配置,取值优先等级websql、缓存、服务器
   * @param {Object}  param   请求参数
   */
  getCacheConfig (param) {
    param.userid = sessionStorage.getItem('UserID') || ''
    param.lang = localStorage.getItem('lang') || ''
    param.SessionUid = localStorage.getItem('SessionUid') || ''
    param.LoginUID = sessionStorage.getItem('LoginUID') || ''
    param.appkey = window.GLOB.appkey || ''
    if (sessionStorage.getItem('isEditState') === 'true') { // 编辑状态,单点登录服务器为云端
      if (options.cloudServiceApi) { // 存在云端地址时,使用云端系统参数
        param.rduri = options.cloudServiceApi
        param.userid = sessionStorage.getItem('CloudUserID') || ''
        param.LoginUID = sessionStorage.getItem('CloudLoginUID') || ''
      }
    } else if (window.GLOB.mainSystemApi) {
      param.rduri = window.GLOB.mainSystemApi
    }
    let _param = JSON.parse(JSON.stringify(param)) // 缓存校验,去除时间和加密字符
    delete _param.timestamp
    delete _param.secretkey
    delete _param.open_key
    _param = JSON.stringify(_param)
    _param  = md5(_param)
    if (mkDB) {
      param.nonc = Utils.getuuid()
      let keys = Object.keys(param).sort()
      let values = ''
      keys.forEach(key => {
        if (key === 'rduri' || key === 't') return
        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()
      return new Promise(resolve => {
        mkDB.transaction(tx => {
          tx.executeSql(`SELECT * FROM CONFIGS WHERE menuid='${param.MenuID}' and userid='${param.userid}'`, [], (tx, results) => {
            let paramItem = results.rows[0]
            if (paramItem) {
              resolve({
                ErrCode: 'S',
                ErrMesg: '',
                LongParam: paramItem.LongParam,
                LongParamUser: paramItem.LongParamUser,
                message: '',
                open_edition: paramItem.openEdition,
                status: true,
                web_edition: paramItem.webEdition
              })
            } else {
              axios({
                url: `/webapi/dostars${param.func ? '/' + param.func : ''}`,
                data: param
              }).then(res => {
                if (res.status) {
                  this.writeInWebSql([param.MenuID, param.MenuID, param.userid, res.open_edition, res.web_edition, res.LongParam, res.LongParamUser])
                }
                resolve(res)
              })
            }
          }, (tx, results) => {
            axios({
              url: `/webapi/dostars${param.func ? '/' + param.func : ''}`,
              data: param
            }).then(res => {
              if (res.status) {
                window.GLOB.CacheMap.set(_param, res)
              }
              resolve(res)
            })
            mkDB = null
            console.warn(results)
          })
        })
      })
    } else if (window.GLOB.CacheMap.has(_param)) {
      return Promise.resolve(window.GLOB.CacheMap.get(_param))
    } else {
      param.nonc = Utils.getuuid()
      let keys = Object.keys(param).sort()
      let values = ''
      keys.forEach(key => {
        if (key === 'rduri' || key === 't') return
        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()
      return new Promise(resolve => {
        axios({
          url: `/webapi/dostars${param.func ? '/' + param.func : ''}`,
          data: param
        }).then(res => {
          if (res.status) {
            window.GLOB.CacheMap.set(_param, res)
          }
          resolve(res)
        })
      })
    }
  }
  /**
   * @description 将数据写入websql
   */
  writeInWebSql (data) {
    if (!mkDB) return
    mkDB.transaction(tx => {
      tx.executeSql('INSERT INTO CONFIGS (id, menuid, userid, openEdition, webEdition, LongParam, LongParamUser) VALUES (?, ?, ?, ?, ?, ?, ?)', data)
    })
  }
  /**
   * @description 获取系统配置,优先从缓存中取值,增加appkey
   * @param {Object}  param   请求参数
   * @param {Boolean} SSO     是否为单点登录地址
@@ -335,6 +564,7 @@
    let _param = JSON.parse(JSON.stringify(param)) // 缓存校验,去除时间和加密字符
    delete _param.timestamp
    delete _param.secretkey
    delete _param.open_key
    _param = JSON.stringify(_param)
    _param  = md5(_param)
src/components/header/index.jsx
@@ -579,7 +579,10 @@
          result.UserRoles.forEach(role => {
            role.RoleMenu.forEach(menu => {
              if (!menu.MenuID) return
              if (menukeys.includes(menu.MenuID)) return
              if (menukeys.includes(menu.MenuID)) {
                console.warn('s_Get_TrdMenu_Role重复的菜单ID:' + menu.MenuID)
                return
              }
              _permMenus[menu.MenuID] = true
              let _type = ''
@@ -692,9 +695,9 @@
        {this.props.editLevel === 'HS' ? <Button className="level4-close" type="primary" onClick={this.exitManage}>退出</Button> : null}
        {/* 进入编辑按钮 */}
        {this.props.editState && !this.props.editLevel ? <Icon onClick={this.enterEdit} className="edit-check" type="edit" /> : null}
        {/* {this.props.editState && !this.props.editLevel && options.sysType === 'local' && window.GLOB.systemType !== 'production' ?
        {this.props.editState && !this.props.editLevel && options.sysType === 'local' && window.GLOB.systemType !== 'production' ?
          <a href="#/mobmanage" target="_blank" className="mobile" type="edit"> 应用管理 <Icon type="arrow-right" /></a> : null
        } */}
        }
        {/* 编辑菜单 */}
        {this.props.editLevel === 'level1' ? <EditMenu menulist={this.state.menulist} reload={this.reload} exitEdit={this.exitEdit}/> : null}
        {/* 头像、用户名 */}
src/index.js
@@ -168,6 +168,22 @@
      document.getElementById('root').className = option[window.GLOB.style]
    }
    let mkDBUseable = false
    if (process.env.NODE_ENV === 'production') { // 是否使用web存储
      mkDBUseable = options.sysType !== 'local' || window.GLOB.systemType === 'production'
    } else {
      mkDBUseable = true
    }
    if (config.webStorage && mkDBUseable) {
      let stor = config.webStorage.toLowerCase()
      if (stor.indexOf('websql') > -1) {
        window.GLOB.webSqlUsable = true
      } else if (stor.indexOf('indexeddb') > -1) {
        window.GLOB.IndexedDBUsable = true
      }
    }
    render(Route)
  })
src/mob/components/login/mob-login-2/index.jsx
@@ -8,6 +8,7 @@
import enUS from '@/locales/en-US/mob.js'
import Utils from '@/utils/utils.js'
import ContentUpdate from '@/mob/contupdate'
import ContentDelete from '@/mob/contdelete'
import './index.scss'
class MobLogin2 extends Component {
@@ -26,30 +27,73 @@
      type: 'login',
      subtype: 'mob-login-2',
      box: { uuid: Utils.getuuid(), eleType: 'box', style: {}},
      title: { uuid: Utils.getuuid(), eleType: 'text', content: '登录', style: {fontSize: '18px', fontWeight: 'bold', color: '#000000', textAlign: 'center', marginTop: '10vh', marginBottom: '10vh'}},
      title: {
        uuid: Utils.getuuid(), eleType: 'text', content: '登录',
        style: {
          fontSize: '18px', fontWeight: 'bold', color: '#000000', textAlign: 'center', marginTop: '10vh', marginBottom: '10vh'
        }
      },
      user: { uuid: Utils.getuuid(), eleType: 'input', content: '邮箱/手机', style: {}},
      password: { uuid: Utils.getuuid(), eleType: 'input', content: '密码', style: {}},
      login: { uuid: Utils.getuuid(), eleType: 'button', content: '登录', style: {fontSize: '16px', color: '#ffffff', textAlign: 'center', lineHeight: 2.4, backgroundColor: '#44a8f2'}},
      phone: { uuid: Utils.getuuid(), eleType: 'button', content: '手机短信登录', style: {fontSize: '16px', color: '#44a8f2', textAlign: 'center', lineHeight: 2.4, border: '1px solid #44a8f2'}},
      register: { uuid: Utils.getuuid(), eleType: 'text', content: '注册', style: {fontSize: '14px', color: '#44a8f2', textAlign: 'left'}},
      lose: { uuid: Utils.getuuid(), eleType: 'text', content: '忘记密码?', style: {fontSize: '14px', color: '#44a8f2', textAlign: 'right', textDecoration: 'underline'}},
      auth: {
        uuid: Utils.getuuid(), eleType: 'text',
        subItems: [
          {type: 'qq', icon: 'qq', label: 'QQ'},
          {type: 'wechat', icon: 'wechat', label: '微信'},
        ],
        content: '其他登录方式', style: {fontSize: '14px', color: '#bcbcbc', textAlign: 'center', marginTop: '30px', marginBottom: '20px'}
      login: {
        uuid: Utils.getuuid(), eleType: 'button', content: '登录',
        style: {
          fontSize: '16px', color: '#ffffff', textAlign: 'center', lineHeight: 2.4, backgroundColor: '#44a8f2'
        }
      },
      copyright: { uuid: Utils.getuuid(), eleType: 'textarea', content: 'Copyright©2017  所有相关版权归  北京明科普华信息技术有限公司', style: {fontSize: '12px', textAlign: 'center'} },
      phone: {
        uuid: Utils.getuuid(), eleType: 'button', content: '手机短信登录',
        style: {
          fontSize: '16px', color: '#44a8f2', textAlign: 'center', lineHeight: 2.4, border: '1px solid #44a8f2'
        }
      },
      register: {
        uuid: Utils.getuuid(), eleType: 'text', content: '注册',
        style: {
          fontSize: '14px', color: '#44a8f2', textAlign: 'left'
        }
      },
      lose: {
        uuid: Utils.getuuid(), eleType: 'text', content: '忘记密码?',
        style: {
          fontSize: '14px', color: '#44a8f2', textAlign: 'right', textDecoration: 'underline'
        }
      },
      auth: {
        uuid: Utils.getuuid(), eleType: 'text', content: '其他登录方式',
        style: {
          fontSize: '14px', color: '#bcbcbc', textAlign: 'center', marginTop: '30px', marginBottom: '20px'
        }
      },
      authlist: {
        uuid: Utils.getuuid(),
        subItems: [
          {uuid: 'qq', type: 'qq', icon: 'qq', label: 'QQ'},
          {uuid: 'wechat', type: 'wechat', icon: 'wechat', label: '微信'},
        ],
      },
      copyright: {
        uuid: Utils.getuuid(), eleType: 'textarea', content: 'Copyright©2017  所有相关版权归  北京明科普华信息技术有限公司',
        style: {
          fontSize: '12px', textAlign: 'center', color: 'rgba(0, 0, 0, 0.65)'
        }
      },
      links: {
        uuid: Utils.getuuid(), eleType: 'link', substyle: false,
        subItems: [
          {eleType: 'link', content: '隐私政策', url: '', uuid: Utils.getuuid()},
          {eleType: 'link', content: '使用条款', url: '', uuid: Utils.getuuid()},
        ],
        style: {fontSize: '12px', textAlign: 'center', color: '#44a8f2', textDecoration: 'underline'}
      }
        style: {
          fontSize: '12px', textAlign: 'center', color: '#44a8f2', textDecoration: 'underline'
        }
      },
      account: {
        uuid: Utils.getuuid(), eleType: 'button', content: '账号密码登录',
        style: {
          fontSize: '16px', color: '#44a8f2', textAlign: 'center', lineHeight: 2.4, border: '1px solid #44a8f2'
        }
      },
    }
  }
@@ -96,7 +140,7 @@
      ...fromJS(card.copyright.style).toJS(),
      componentId: card.uuid,
      uuid: card.copyright.uuid,
      items: ['font'],
      items: ['font', 'margin'],
    }
    this.props.triggerEdit(element)
  }
@@ -121,7 +165,7 @@
      ...fromJS(card[type].style).toJS(),
      componentId: card.uuid,
      uuid: card[type].uuid,
      items: ['font', 'background', 'border']
      items: ['font', 'background', 'border', 'margin']
    }
    this.props.triggerEdit(element)
  }
@@ -226,77 +270,153 @@
      titleStyle.marginBottom = `calc(${(percent / 100) * 615}px)`
    }
    if (view === 'account') return (
      <div className="mob-login-2" onClick={this.editBox} style={card.box.style}>
        {card.title ? <div className={'plat-name ' + (editId === card.title.uuid ? 'editing' : '')} style={titleStyle} onClick={this.editTitle}>
          <ContentUpdate element={card.title} updateContent={(ele) => this.updateContent({...card, title: ele})}/>
          {card.title.content}
        </div> : null}
        <div className={`mk-login-input ${editId === card.user.uuid ? 'editing' : ''}`} onClick={(e) => this.editPlaceholder(e, 'user')}>
          <ContentUpdate element={card.user} deletable={false} updateContent={(ele) => this.updateContent({...card, user: ele})}/>
          <InputItem placeholder={card.user.content}></InputItem>
        </div>
        <div className={`mk-login-input ${editId === card.password.uuid ? 'editing' : ''}`} onClick={(e) => this.editPlaceholder(e, 'password')}>
          <ContentUpdate element={card.password} deletable={false} updateContent={(ele) => this.updateContent({...card, password: ele})}/>
          <InputItem placeholder={card.password.content}></InputItem>
        </div>
        <Button
          className={'login ' + (editId === card.login.uuid ? 'editing' : '')}
          onDoubleClick={() => this.props.doubleClickCard(card.login)}
          style={card.login.style}
          onClick={(e) => this.editLogin(e, 'login')}
        >
          <ContentUpdate element={card.login} deletable={false} updateContent={(ele) => this.updateContent({...card, login: ele})}/>
          {card.login.content}
        </Button>
        <Button
          className={'login ' + (editId === card.phone.uuid ? 'editing' : '')}
          onDoubleClick={() => this.props.doubleClickCard(card.phone)}
          style={card.phone.style}
          onClick={(e) => this.editLogin(e, 'phone')}
        >
          <ContentUpdate element={card.phone} updateContent={(ele) => this.updateContent({...card, phone: ele})}/>
          {card.phone.content}
        </Button>
        <div className="row-box">
          {card.register ? <div className={'col-item ' + (editId === card.register.uuid ? 'editing' : '')} style={card.register.style} onClick={this.editRegister}>
            <ContentUpdate element={card.register} updateContent={(ele) => this.updateContent({...card, register: ele})}/>
            {card.register.content}
    if (view === 'account') {
      return (
        <div className="mob-login-2" onClick={this.editBox} style={card.box.style}>
          {card.title ? <div className={'plat-name ' + (editId === card.title.uuid ? 'editing' : '')} style={titleStyle} onClick={this.editTitle}>
            <ContentUpdate element={card.title} updateContent={(ele) => this.updateContent({...card, title: ele})}/>
            {card.title.content}
          </div> : null}
          {card.lose ? <div className={'col-item right ' + (editId === card.lose.uuid ? 'editing' : '')} style={card.lose.style} onClick={this.editLose}>
            <ContentUpdate element={card.lose} updateContent={(ele) => this.updateContent({...card, lose: ele})}/>
            {card.lose.content}
          <div className={`mk-login-input ${editId === card.user.uuid ? 'editing' : ''}`} onClick={(e) => this.editPlaceholder(e, 'user')}>
            <ContentUpdate element={card.user} deletable={false} updateContent={(ele) => this.updateContent({...card, user: ele})}/>
            <InputItem disabled={true} placeholder={card.user.content}></InputItem>
          </div>
          <div className={`mk-login-input ${editId === card.password.uuid ? 'editing' : ''}`} onClick={(e) => this.editPlaceholder(e, 'password')}>
            <ContentUpdate element={card.password} deletable={false} updateContent={(ele) => this.updateContent({...card, password: ele})}/>
            <InputItem disabled={true} placeholder={card.password.content}></InputItem>
          </div>
          <Button
            className={'login ' + (editId === card.login.uuid ? 'editing' : '')}
            onDoubleClick={() => this.props.doubleClickCard(card.login)}
            style={card.login.style}
            onClick={(e) => this.editLogin(e, 'login')}
          >
            <ContentUpdate element={card.login} deletable={false} updateContent={(ele) => this.updateContent({...card, login: ele})}/>
            {card.login.content}
          </Button>
          <Button
            className={'login ' + (editId === card.phone.uuid ? 'editing' : '')}
            onDoubleClick={() => this.setState({view: 'phone'})}
            style={card.phone.style}
            onClick={(e) => this.editLogin(e, 'phone')}
          >
            <ContentUpdate element={card.phone} updateContent={(ele) => this.updateContent({...card, phone: ele})}/>
            {card.phone.content}
          </Button>
          <div className="row-box">
            {card.register ? <div className={'col-item ' + (editId === card.register.uuid ? 'editing' : '')} style={card.register.style} onClick={this.editRegister}>
              <ContentUpdate element={card.register} updateContent={(ele) => this.updateContent({...card, register: ele})}/>
              {card.register.content}
            </div> : null}
            {card.lose ? <div className={'col-item right ' + (editId === card.lose.uuid ? 'editing' : '')} style={card.lose.style} onClick={this.editLose}>
              <ContentUpdate element={card.lose} updateContent={(ele) => this.updateContent({...card, lose: ele})}/>
              {card.lose.content}
            </div> : null}
            <div style={{clear: 'both'}}></div>
          </div>
          {card.auth ? <div className={'plat-name ' + (editId === card.auth.uuid ? 'editing' : '')} style={card.auth.style} onClick={this.editAuth}>
            <ContentUpdate element={card.auth} updateContent={(ele) => this.updateContent({...card, auth: ele})}/>
            {card.auth.content}
          </div> : null}
          <div style={{clear: 'both'}}></div>
          {card.authlist ? <div className="other-auth">
            {card.authlist.subItems.map(cell => (
              <span className="deletable-item" key={cell.type}>
                <ContentDelete element={cell} list={card.authlist} updateContent={(ele) => this.updateContent({...card, authlist: ele})}/>
                <Icon type={cell.icon} />
                <p>{cell.label}</p>
              </span>
            ))}
          </div> : null}
          {card.copyright ? <div className={'company-msg ' + (editId === card.copyright.uuid ? 'editing' : '')} style={card.copyright.style} onClick={this.editMsg}>
            <ContentUpdate element={card.copyright} updateContent={(ele) => this.updateContent({...card, copyright: ele})}/>
            {card.copyright.content}
          </div> : null}
          {card.links ? <div className="links" style={card.links.style}>
            {card.links.subItems.map(item => (
              <span className={(editId === item.uuid ? 'editing' : '')} key={item.uuid} onClick={(e) => this.editLinks(e, item)}>
                <ContentUpdate element={item} updateContent={(val) => this.updateLinkItem(val, item)}/>
                {item.content}
              </span>
            ))}
            <Icon type="plus" onClick={this.linkItemAdd} />
          </div> : null}
        </div>
        {card.auth ? <div className={'plat-name ' + (editId === card.auth.uuid ? 'editing' : '')} style={card.auth.style} onClick={this.editAuth}>
          <ContentUpdate element={card.auth} updateContent={(ele) => this.updateContent({...card, auth: ele})}/>
          {card.auth.content}
        </div> : null}
        {card.auth ? <div className="other-auth">
          {card.auth.subItems.map(cell => (
            <span key={cell.type}>
              <Icon type={cell.icon} />
              <p>{cell.label}</p>
            </span>
          ))}
        </div> : null}
        {card.copyright ? <div className={'company-msg ' + (editId === card.copyright.uuid ? 'editing' : '')} style={card.copyright.style} onClick={this.editMsg}>
          <ContentUpdate element={card.copyright} updateContent={(ele) => this.updateContent({...card, copyright: ele})}/>
          {card.copyright.content}
        </div> : null}
        {card.links ? <div className="links" style={card.links.style}>
          {card.links.subItems.map(item => (
            <span className={(editId === item.uuid ? 'editing' : '')} key={item.uuid} onClick={(e) => this.editLinks(e, item)}>
              <ContentUpdate element={item} updateContent={(val) => this.updateLinkItem(val, item)}/>
              {item.content}
            </span>
          ))}
          <Icon type="plus" onClick={this.linkItemAdd} />
        </div> : null}
      </div>
    )
      )
    } else if (view === 'phone') {
      return (
        <div className="mob-login-2" onClick={this.editBox} style={card.box.style}>
          {card.title ? <div className={'plat-name ' + (editId === card.title.uuid ? 'editing' : '')} style={titleStyle} onClick={this.editTitle}>
            <ContentUpdate element={card.title} updateContent={(ele) => this.updateContent({...card, title: ele})}/>
            {card.title.content}
          </div> : null}
          <div className={`mk-login-input ${editId === card.user.uuid ? 'editing' : ''}`} onClick={(e) => this.editPlaceholder(e, 'user')}>
            <ContentUpdate element={card.user} deletable={false} updateContent={(ele) => this.updateContent({...card, user: ele})}/>
            <InputItem disabled={true} placeholder={card.user.content}></InputItem>
          </div>
          <div className={`mk-login-input ${editId === card.password.uuid ? 'editing' : ''}`} onClick={(e) => this.editPlaceholder(e, 'password')}>
            <ContentUpdate element={card.password} deletable={false} updateContent={(ele) => this.updateContent({...card, password: ele})}/>
            <InputItem disabled={true} placeholder={card.password.content}></InputItem>
          </div>
          <Button
            className={'login ' + (editId === card.login.uuid ? 'editing' : '')}
            onDoubleClick={() => this.props.doubleClickCard(card.login)}
            style={card.login.style}
            onClick={(e) => this.editLogin(e, 'login')}
          >
            <ContentUpdate element={card.login} deletable={false} updateContent={(ele) => this.updateContent({...card, login: ele})}/>
            {card.login.content}
          </Button>
          <Button
            className={'login ' + (editId === card.account.uuid ? 'editing' : '')}
            onDoubleClick={() => this.setState({view: 'account'})}
            style={card.account.style}
            onClick={(e) => this.editLogin(e, 'account')}
          >
            <ContentUpdate element={card.account} updateContent={(ele) => this.updateContent({...card, account: ele})}/>
            {card.account.content}
          </Button>
          <div className="row-box">
            {card.register ? <div className={'col-item ' + (editId === card.register.uuid ? 'editing' : '')} style={card.register.style} onClick={this.editRegister}>
              <ContentUpdate element={card.register} updateContent={(ele) => this.updateContent({...card, register: ele})}/>
              {card.register.content}
            </div> : null}
            {card.lose ? <div className={'col-item right ' + (editId === card.lose.uuid ? 'editing' : '')} style={card.lose.style} onClick={this.editLose}>
              <ContentUpdate element={card.lose} updateContent={(ele) => this.updateContent({...card, lose: ele})}/>
              {card.lose.content}
            </div> : null}
            <div style={{clear: 'both'}}></div>
          </div>
          {card.auth ? <div className={'plat-name ' + (editId === card.auth.uuid ? 'editing' : '')} style={card.auth.style} onClick={this.editAuth}>
            <ContentUpdate element={card.auth} updateContent={(ele) => this.updateContent({...card, auth: ele})}/>
            {card.auth.content}
          </div> : null}
          {card.authlist ? <div className="other-auth">
            {card.authlist.subItems.map(cell => (
              <span className="deletable-item" key={cell.type}>
                <ContentDelete element={cell} list={card.authlist} updateContent={(ele) => this.updateContent({...card, authlist: ele})}/>
                <Icon type={cell.icon} />
                <p>{cell.label}</p>
              </span>
            ))}
          </div> : null}
          {card.copyright ? <div className={'company-msg ' + (editId === card.copyright.uuid ? 'editing' : '')} style={card.copyright.style} onClick={this.editMsg}>
            <ContentUpdate element={card.copyright} updateContent={(ele) => this.updateContent({...card, copyright: ele})}/>
            {card.copyright.content}
          </div> : null}
          {card.links ? <div className="links" style={card.links.style}>
            {card.links.subItems.map(item => (
              <span className={(editId === item.uuid ? 'editing' : '')} key={item.uuid} onClick={(e) => this.editLinks(e, item)}>
                <ContentUpdate element={item} updateContent={(val) => this.updateLinkItem(val, item)}/>
                {item.content}
              </span>
            ))}
            <Icon type="plus" onClick={this.linkItemAdd} />
          </div> : null}
        </div>
      )
    }
  }
}
src/mob/components/login/mob-login-2/index.scss
@@ -55,6 +55,7 @@
    color: rgb(68, 168, 242);
    span {
      position: relative;
      display: inline-block;
      vertical-align: top;
      p {
@@ -78,6 +79,10 @@
    margin-bottom: 10px;
    border: 1px solid #dddddd;
    .am-input-control input:disabled {
      color: rgba(0, 0, 0, 0.65);
    }
    .am-input-label {
      width: 30px;
      color: inherit;
src/mob/contdelete/index.jsx
New file
@@ -0,0 +1,59 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
// import { is, fromJS } from 'immutable'
import { Icon, Modal } from 'antd'
import zhCN from '@/locales/zh-CN/mob.js'
import enUS from '@/locales/en-US/mob.js'
import './index.scss'
const { confirm } = Modal
class ContentDelete extends Component {
  static propTpyes = {
    element: PropTypes.object,
    list: PropTypes.array,
    updateContent: PropTypes.func
  }
  state = {
    dict: localStorage.getItem('lang') !== 'en-US' ? zhCN : enUS,
    images: [],
    visible: false
  }
  UNSAFE_componentWillMount () {
  }
  // shouldComponentUpdate (nextProps, nextState) {
  //   return !is(fromJS(this.props), fromJS(nextProps)) || !is(fromJS(this.state), fromJS(nextState))
  // }
  deleteElement = () => {
    const { list, element } = this.props
    const _this = this
    confirm({
      title: '确定删除元素吗?',
      okText: this.state.dict['mob.confirm'],
      cancelText: this.state.dict['mob.cancel'],
      onOk() {
        _this.props.updateContent({...list, subItems: list.subItems.filter(item => item.uuid !== element.uuid)})
      },
      onCancel() {}
    })
  }
  render () {
    return (
      <div className="mob-content-list-delete">
        <Icon type="close" onClick={this.deleteElement} />
      </div>
    )
  }
}
export default ContentDelete
src/mob/contdelete/index.scss
New file
@@ -0,0 +1,25 @@
.mob-content-list-delete {
  position: absolute;
  top: -10px;
  left: -10px;
  border-radius: 2px;
  font-size: 14px;
  display: none;
  line-height: 1.5;
  z-index: 1;
  i {
    padding: 2px 5px;
    cursor: pointer;
  }
  .anticon-close {
    color: #ff4d4f;
  }
}
.deletable-item {
  position: relative;
}
.deletable-item:hover .mob-content-list-delete {
  display: inline-block;
}
src/mob/contupdate/index.jsx
@@ -76,6 +76,8 @@
    confirm({
      title: '确定删除元素吗?',
      okText: this.state.dict['mob.confirm'],
      cancelText: this.state.dict['mob.cancel'],
      onOk() {
        _this.props.updateContent(null)
      },
src/mob/datasource/index.jsx
@@ -107,7 +107,13 @@
  }
  render () {
    const { config } = this.props
    const { sourcelist, visible, source, dict, searches, loading } = this.state
    let addable = true
    if (config.components && config.components.length === 1 && config.components[0].type === 'login') {
      addable = false
    }
    return (
      <div className="mob-datasource">
@@ -122,15 +128,15 @@
            </span>
          </span>
        ))}
        <span className="mob-input-group-wrapper">
        {addable ? <span className="mob-input-group-wrapper">
          <span className="mob-input-wrapper">
            <span className="mob-input-insert" onClick={() => this.editDataSource()}>
              <Icon type="plus" />
            </span>
          </span>
        </span>
        </span> : null}
        <Modal
          wrapClassName="mob-datasource-verify-modal"
          wrapClassName="mob-datasource-verify-modal popview-modal"
          title={'数据源配置'}
          visible={visible}
          width={'75vw'}
src/mob/datasource/index.scss
@@ -78,4 +78,12 @@
      color: #ff4d4f;
    }
  }
}
.mob-datasource-verify-modal {
  .ant-modal {
    top: 50px;
    .ant-modal-body {
      max-height: calc(100vh - 190px);
    }
  }
}
src/mob/datasource/verifycard/customscript/index.jsx
@@ -1,11 +1,10 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import { Form, Row, Col, Input, Button, notification, Select } from 'antd'
import { Form, Row, Col, Button, notification, Select } from 'antd'
import Utils from '@/utils/utils.js'
import CodeMirror from '@/templates/zshare/codemirror'
import './index.scss'
const { TextArea } = Input
class CustomForm extends Component {
  static propTpyes = {
@@ -218,7 +217,7 @@
                    message: this.props.dict['mob.required.input'] + 'sql!'
                  }
                ]
              })(<TextArea rows={15} />)}
              })(<CodeMirror />)}
            </Form.Item>
          </Col>
        </Row>
src/mob/datasource/verifycard/customscript/index.scss
@@ -27,5 +27,8 @@
      width: 89.5%;
      padding-top: 4px;
    }
    .CodeMirror {
      height: 350px;
    }
  }
}
src/tabviews/commontable/index.jsx
@@ -84,7 +84,7 @@
      func: 'sPC_Get_LongParam',
      MenuID: this.props.MenuID
    }
    let result = await Api.getSystemCacheConfig(_param)
    let result = await Api.getCacheConfig(_param)
    if (result.status) {
      let config = ''
src/tabviews/formtab/index.jsx
@@ -60,7 +60,7 @@
      func: 'sPC_Get_LongParam',
      MenuID: this.props.MenuID
    }
    let result = await Api.getSystemCacheConfig(param)
    let result = await Api.getCacheConfig(param)
    if (result.status) {
      let config = ''
src/tabviews/subtable/index.jsx
@@ -110,7 +110,7 @@
      func: 'sPC_Get_LongParam',
      MenuID: this.props.MenuID
    }
    let result = await Api.getSystemCacheConfig(param)
    let result = await Api.getCacheConfig(param)
    if (result.status) {
      let config = ''
src/tabviews/subtabtable/index.jsx
@@ -68,7 +68,7 @@
      func: 'sPC_Get_LongParam',
      MenuID: this.props.MenuID
    }
    let result = await Api.getSystemCacheConfig(param)
    let result = await Api.getCacheConfig(param)
    if (result.status) {
      let config = ''
src/tabviews/treepage/index.jsx
@@ -68,7 +68,7 @@
      func: 'sPC_Get_LongParam',
      MenuID: this.props.MenuID
    }
    let result = await Api.getSystemCacheConfig(_param)
    let result = await Api.getCacheConfig(_param)
    if (result.status) {
      let config = ''
src/tabviews/zshare/actionList/normalbutton/index.jsx
@@ -802,7 +802,7 @@
        })
      }
    } else {
      Api.getSystemCacheConfig({
      Api.getCacheConfig({
        func: 'sPC_Get_LongParam',
        MenuID: btn.uuid
      }).then(res => {
src/tabviews/zshare/actionList/printbutton/index.jsx
@@ -1020,7 +1020,7 @@
        })
      }
    } else {
      Api.getSystemCacheConfig({
      Api.getCacheConfig({
        func: 'sPC_Get_LongParam',
        MenuID: btn.uuid
      }).then(res => {
src/tabviews/zshare/verifycard/index.jsx
@@ -80,7 +80,7 @@
            func: 'sPC_Get_LongParam',
            MenuID: tab.linkTab
          }
          Api.getSystemCacheConfig(param).then(res => {
          Api.getCacheConfig(param).then(res => {
            res.tab = tab
            resolve(res)
          })
src/templates/sharecomponent/treesettingcomponent/settingform/customscript/index.jsx
@@ -1,14 +1,13 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import { Form, Row, Col, Input, Button, notification, Modal, Select } from 'antd'
import { Form, Row, Col, Button, notification, Modal, Select } from 'antd'
import moment from 'moment'
import Utils from '@/utils/utils.js'
import SettingUtils from '../utils.jsx'
import CodeMirror from '@/templates/zshare/codemirror'
import Api from '@/api'
import './index.scss'
const { TextArea } = Input
class CustomForm extends Component {
  static propTpyes = {
@@ -238,7 +237,7 @@
                    message: this.props.dict['form.required.input'] + 'sql!'
                  }
                ]
              })(<TextArea rows={15} />)}
              })(<CodeMirror />)}
            </Form.Item>
          </Col>
        </Row>
src/templates/sharecomponent/treesettingcomponent/settingform/customscript/index.scss
@@ -27,5 +27,8 @@
      width: 89.5%;
      padding-top: 4px;
    }
    .CodeMirror {
      height: 350px;
    }
  }
}
src/templates/sharecomponent/treesettingcomponent/settingform/index.jsx
@@ -8,9 +8,9 @@
import Utils from '@/utils/utils.js'
import SettingUtils from './utils.jsx'
import CustomScript from './customscript'
import CodeMirror from '@/templates/zshare/codemirror'
import './index.scss'
const { TextArea } = Input
const { confirm } = Modal
const { Paragraph } = Typography
@@ -568,7 +568,7 @@
      } else if (item.type === 'datasource') {
        fields.push(
          <Col span={24} key={index} style={{paddingLeft: '7px'}}>
            <Form.Item labelCol={{xs: { span: 24 }, sm: { span: 4 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 20 }} } help={item.help} label={
            <Form.Item className="text-area" labelCol={{xs: { span: 24 }, sm: { span: 4 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 20 }} } help={item.help} label={
              <Tooltip placement="topLeft" title={item.tooltip}>
                <Icon type="question-circle" />
                {item.label}
@@ -576,23 +576,7 @@
            }>
              {getFieldDecorator(item.key, {
                initialValue: item.initVal
              })(<TextArea rows={4} />)}
            </Form.Item>
          </Col>
        )
      } else if (item.type === 'textarea') {
        fields.push(
          <Col span={20} offset={4} key={index}>
            <Form.Item className="text-area">
              {getFieldDecorator(item.key, {
                initialValue: item.initVal,
                rules: [
                  {
                    required: !!item.required,
                    message: this.props.dict['form.required.input'] + item.label + '!'
                  }
                ]
              })(<TextArea rows={4} />)}
              })(<CodeMirror />)}
            </Form.Item>
          </Col>
        )
src/templates/sharecomponent/treesettingcomponent/settingform/index.scss
@@ -1,12 +1,9 @@
.model-tree-setting-form-box {
  position: relative;
  .model-tree-setting-form {
    .textarea {
      .ant-form-item-label {
        width: 16.3%;
      }
      .ant-form-item-control-wrapper {
        width: 83.33333333%;
    .text-area {
      .CodeMirror {
        height: 150px;
      }
    }
    .anticon-question-circle {
src/views/login/index.jsx
@@ -222,17 +222,7 @@
          this.setState({touristLogin: true})
        }
        // 获取系统信息
        let _param = {
          func: 's_Get_style',
          TypeCharOne: 'PC',
          LText: `select '${window.GLOB.appkey}'`,
        }
        _param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss') + '.000'
        _param.secretkey = Utils.encrypt(_param.LText, _param.timestamp)
        Api.getSystemConfig(_param).then(res => {
        Api.getSystemStyle().then(res => {
          if (res.status) {
            let _url = window.location.href.split('#')[0] + 'system'
            let systemMsg = {