king
2021-09-08 6d71b3fac75a35e8ebf08e71ba40c5be8a586024
2021-09-08
17个文件已修改
4个文件已添加
872 ■■■■ 已修改文件
src/api/index.js 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/header/index.jsx 53 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/header/versions/index.jsx 511 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/header/versions/index.scss 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/header/versions/settingform/index.jsx 118 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/header/versions/settingform/index.scss 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/card/cardcellcomponent/formconfig.jsx 16 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/table/normal-table/index.jsx 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/pastecontroller/index.jsx 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pc/components/login/normal-login/index.scss 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pc/createview/index.jsx 29 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pc/createview/settingform/index.jsx 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pc/createview/settingform/index.scss 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/table/normal-table/index.scss 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/verupmanage/config.jsx 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/zshare/formconfig.jsx 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/zshare/modalform/index.jsx 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/login/index.scss 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/menudesign/index.jsx 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mobdesign/index.jsx 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/pcdesign/index.jsx 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/index.js
@@ -288,7 +288,6 @@
   * @description 获取系统版本信息,启用或更新websql
   */
  getAppVersion (_resolve, _reject) {
    let appVersion = {}
    if (!window.GLOB.WebSql && !window.GLOB.IndexDB) {
      return Promise.reject()
    }
@@ -304,7 +303,6 @@
    if (window.GLOB.WebSql) {
      return new Promise((resolve, reject) => {
        CacheUtils.getWebSqlVersion().then(msg => {
          appVersion.oldVersion = msg.version || ''
          let modifydate = msg.createDate || curTime
          if (modifydate.indexOf('Invalid date') > -1) {
            modifydate = curTime
@@ -321,9 +319,7 @@
              return
            }
            let clear = false
            let version = res.app_version || '1.00'
            appVersion.newVersion = version
            appVersion.oldVersion = appVersion.oldVersion || version
            let version = '1.00'
  
            if (res.menu_data && res.menu_data.length > 0) {
              res.menu_data.forEach(mid => {
@@ -346,7 +342,7 @@
              CacheUtils.createWebSqlversion(version, curTime)
            }
  
            resolve(appVersion)
            resolve()
          })
        }, () => {
          reject()
@@ -355,7 +351,6 @@
    } else {
      return new Promise((resolve, reject) => {
        CacheUtils.getIndexDBVersion().then(msg => {
          appVersion.oldVersion = msg.version || ''
          let modifydate = msg.createDate || curTime
          if (modifydate.indexOf('Invalid date') > -1) {
            modifydate = curTime
@@ -371,9 +366,7 @@
              return
            }
            let clear = false
            let version = res.app_version || '1.00'
            appVersion.newVersion = version
            appVersion.oldVersion = appVersion.oldVersion || version
            let version = '1.00'
  
            if (res.menu_data && res.menu_data.length > 0) {
              res.menu_data.forEach(mid => {
@@ -390,9 +383,9 @@
              }
            }
            CacheUtils.updateIndexDBversion({version: appVersion.oldVersion, createDate: curTime})
            CacheUtils.updateIndexDBversion({version: version, createDate: curTime})
  
            resolve(appVersion)
            resolve()
          })
        }, () => {
          reject()
@@ -404,12 +397,12 @@
  /**
   * @description 更新系统版本信息,清空配置信息
   */
  updateAppVersion (newVersion) {
  updateAppVersion () {
    let curTime = moment().format('YYYY-MM-DD HH:mm:ss') + '.000'
    CacheUtils.clearWebSqlConfig()
    CacheUtils.updateWebSqlversion(newVersion, curTime)
    CacheUtils.updateWebSqlversion('1.00', curTime)
    CacheUtils.clearIndexDBConfig()
    CacheUtils.updateIndexDBversion({version: newVersion, createDate: curTime})
    CacheUtils.updateIndexDBversion({version: '1.00', createDate: curTime})
  }
  /**
src/components/header/index.jsx
@@ -4,7 +4,7 @@
import {connect} from 'react-redux'
import { is, fromJS } from 'immutable'
import moment from 'moment'
import { Dropdown, Menu, Icon, Modal, Form, notification, Switch, Input, Badge } from 'antd'
import { Dropdown, Menu, Icon, Modal, Form, notification, Switch, Input } from 'antd'
import {
  toggleCollapse,
@@ -22,12 +22,14 @@
import enUS from '@/locales/en-US/main.js'
import Utils from '@/utils/utils.js'
import avatar from '@/assets/img/avatar.jpg'
import asyncComponent from '@/utils/asyncComponent'
import Resetpwd from './resetpwd'
import LoginForm from './loginform'
import './index.scss'
const { confirm } = Modal
const { Search } = Input
const VersionsUp = asyncComponent(() => import('./versions'))
class Header extends Component {
  static propTpyes = {
@@ -46,8 +48,6 @@
    systems: [],
    searchkey: '',
    thdMenuList: [],
    oriVersion: '',
    newVersion: '',
    debug: sessionStorage.getItem('debug') === 'true',
    navBar: ['linkage_navigation', 'linkage', 'menu_board', 'menu_board_navigation'].includes(window.GLOB.navBar) ? 'topmenu' : '',
    menuType: window.GLOB.navBar
@@ -596,12 +596,7 @@
  componentDidMount () {
    // 获取系统的版本信息,延时查询
    setTimeout(() => {
      Api.getAppVersion().then(res => {
        this.setState({
          oriVersion: res.oldVersion,
          newVersion: res.newVersion
        })
      }, () => {})
      Api.getAppVersion().then(() => {}, () => {})
    }, 1000)
  }
@@ -616,38 +611,6 @@
    this.setState = () => {
      return
    }
  }
  verup = () => {
    const { oriVersion, newVersion } = this.state
    const _this = this
    confirm({
      title: this.state.dict['main.verup'],
      content: `最新版本${newVersion},当前版本${oriVersion}`,
      onOk() {
        return new Promise(resolve => {
          if (!window.GLOB.WebSql) {
            notification.warning({
              top: 92,
              message: '升级失败,请刷新页面重试!',
              duration: 2
            })
            resolve()
          } else {
            Api.updateAppVersion(newVersion)
            notification.success({
              top: 92,
              message: '升级成功!',
              duration: 2
            })
            _this.setState({oriVersion: newVersion})
            resolve()
          }
        })
      },
      onCancel() {}
    })
  }
  gotoDoc = () => {
@@ -702,7 +665,7 @@
  render () {
    const { mainMenu, collapse } = this.props
    const { thdMenuList, searchkey, oriVersion, newVersion, debug, menulist, navBar, menuType } = this.state
    const { thdMenuList, searchkey, debug, menulist, navBar, menuType } = this.state
    const menu = (
      <Menu className="header-dropdown">
@@ -717,9 +680,9 @@
          ))}
        </Menu.SubMenu> : null}
        <Menu.Item key="doc" onClick={this.gotoDoc}>{this.state.dict['main.doc']}</Menu.Item>
        {oriVersion ? <Menu.Item key="verup" onClick={this.verup}>
          <Badge dot={oriVersion !== newVersion}>{this.state.dict['main.verup']}</Badge>
        </Menu.Item> : null}
        <Menu.Item style={{padding: 0}} key="verup">
          <VersionsUp debug={debug} />
        </Menu.Item>
        <Menu.Item key="logout" onClick={this.logout}>{this.state.dict['main.logout']}</Menu.Item>
      </Menu>
    )
src/components/header/versions/index.jsx
New file
@@ -0,0 +1,511 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import { is, fromJS } from 'immutable'
import { Modal, notification, Timeline, Icon, Button } from 'antd'
import moment from 'moment'
import md5 from 'md5'
// import SettingForm from './settingform'
import Api from '@/api'
import options from '@/store/options.js'
import Utils from '@/utils/utils.js'
import './index.scss'
const { confirm } = Modal
class DataSource extends Component {
  static propTpyes = {
    debug: PropTypes.any
  }
  state = {
    visible: false,
    versions: null,
    version: null,
    error: false
  }
  shouldComponentUpdate (nextProps, nextState) {
    return !is(fromJS(this.state), fromJS(nextState))
  }
  verup = () => {
    const { debug } = this.props
    if (!debug || options.sysType === 'cloud') {
      confirm({
        title: '版本升级',
        content: '重新加载应用信息',
        onOk() {
          return new Promise(resolve => {
            if (!window.GLOB.WebSql && !window.GLOB.IndexDB) {
              notification.warning({
                top: 92,
                message: '升级失败,请刷新页面重试!',
                duration: 2
              })
              resolve()
            } else {
              Api.updateAppVersion()
              setTimeout(() => {
                notification.success({
                  top: 92,
                  message: '升级成功!',
                  duration: 2
                })
                resolve()
              }, 1000)
            }
          })
        },
        onCancel() {}
      })
    } else {
      Api.updateAppVersion()
      if (!sessionStorage.getItem('CloudUserID') || !sessionStorage.getItem('CloudLoginUID')) {
        notification.warning({
          top: 92,
          message: '请登录开发机!',
          duration: 2
        })
        return
      }
      let _param = {
        func: 's_get_sversions_sys',
      }
      Api.getSystemConfig(_param).then(result => {
        if (!result.status) {
          notification.warning({
            top: 92,
            message: result.message,
            duration: 5
          })
          return
        }
        let edition_int = ''
        if (options.sysType === 'SSO') {
          edition_int = result.edition_int_sso
        } else if (options.sysType === 'local' && window.GLOB.systemType !== 'production') {
          edition_int = result.edition_int_local
        } else {
          if (result.edition_int_sso < result.edition_int_local) {
            edition_int = result.edition_int_sso
          } else {
            edition_int = result.edition_int_local
          }
        }
        if (edition_int === '') {
          notification.warning({
            top: 92,
            message: '未查询到更新版本信息!',
            duration: 5
          })
          return
        }
        let _rduri = window.atob('aHR0cHM6Ly9lcGMubWs5aC5$mkjbi93ZWJhcGkvZG9zdGFycw=='.replace(/\$mk/ig, ''))
        let _id = window.atob('YmgwYmFwYWJ0ZDQ1ZXBz$mkZ3JhNzlzZWdiY2g2YzFpYms='.replace(/\$mk/ig, ''))
        let sysType = options.sysType.toLowerCase()
        if (window.GLOB.systemType === 'production') {
          sysType = ''
        }
        let param = {
          func: 's_get_sversions_sys_epc',
          appkey: window.GLOB.appkey,
          userid: _id,
          LoginUID: _id,
          edition_int: edition_int,
          sys_type: sysType,
          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(_rduri + '/s_get_sversions_sys_epc', 'post', param, 'true').then(res => {
          if (!res.status) {
            notification.warning({
              top: 92,
              message: res.message,
              duration: 5
            })
            return
          } else if (!res.data || res.data.length === 0) {
            notification.success({
              top: 92,
              message: '已经是最新的版本了。',
              duration: 2
            })
            return
          }
          res.data = res.data.map((item, i) => {
            item.status = i === 0 ? 'loading' : 'waiting'
            item.index = i
            return item
          })
          this.setState({versions: res.data, version: res.data[0], visible: true}, () => {
            this.queryScript()
          })
        })
      })
    }
  }
  queryScript = () => {
    const { version } = this.state
    let _param = {
      func: 's_get_sVersiondetail_Up',
      VersionName: version.id,
      BID: ''
    }
    Api.getCloudConfig(_param).then(res => {
      delete res.message
      delete res.status
      res.func = 's_sVersion_Local_add'
      res.VersionName = version.id
      Api.getLocalConfig(res).then(result => {
        if (!result.status) {
          notification.warning({
            top: 92,
            message: result.message,
            duration: 5
          })
          this.execError()
          return
        } else if (!result.vid) {
          notification.warning({
            top: 92,
            message: '当前应用需要升级系统接口,请联系管理员!',
            duration: 5
          })
          this.execError()
          return
        }
        this.setState({version: {...version, BID: result.vid}})
        let sql = `select ID,KeyWords,Remark,TypeName,Sort,SrcID from (select * from sVersionDetail_Local where BID='${result.vid}' and deleted=0 and status=0 ) tmptable order by Sort`
        let param = {
          func: 'sPC_Get_TableData',
          obj_name: 'data',
          arr_field: 'ID,KeyWords,Remark,TypeName,Sort,SrcID',
          BID: '',
        }
        param.LText = Utils.formatOptions(sql)
        param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
        param.secretkey = Utils.encrypt(param.LText, param.timestamp)
        param.DateCount = ''
        Api.getLocalConfig(param).then(response => {
          if (!response.status) {
            notification.warning({
              top: 92,
              message: response.message,
              duration: 5
            })
            this.execError()
            return
          } else if (!response.data || response.data.length === 0) {
            this.next()
          } else {
            this.loopRequest(response.data)
          }
        }, () => { this.execError() })
      }, () => { this.execError() })
    }, () => { this.execError() })
  }
  loopRequest = (scripts) => {
    const { version } = this.state
    if (!version) return
    let script = scripts.shift()
    let param = {
      func: 's_get_sVersionDetail_Ltext',
      SrcID: script.SrcID,
      ID: script.ID,
      BID: version.BID
    }
    let ssoParam = {
      func: 's_sDataDictb_TBBack',
      SrcID: script.SrcID,
      ID: script.ID,
      BID: version.BID
    }
    let localParam = {
      func: 's_sDataDictb_TBBack',
      SrcID: script.SrcID,
      ID: script.ID,
      BID: version.BID
    }
    Api.getCloudConfig(param).then(res => {
      delete res.message
      delete res.status
      localParam = {...localParam, ...res}
      if (res.LTextOut) {
        localParam.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
        localParam.secretkey = Utils.encrypt(localParam.LTextOut, localParam.timestamp)
        localParam.open_key = Utils.encryptOpenKey(localParam.secretkey, localParam.timestamp)
      }
      if (res.UpType === 'SSO' && window.GLOB.mainSystemApi) {
        ssoParam = {...ssoParam, ...res}
        delete ssoParam.UpType
        ssoParam.rduri = window.GLOB.mainSystemApi
        if (res.LTextOut) {
          ssoParam.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
          ssoParam.secretkey = Utils.encrypt(ssoParam.LTextOut, ssoParam.timestamp)
          ssoParam.open_key = Utils.encryptOpenKey(ssoParam.secretkey, ssoParam.timestamp)
        }
      } else {
        delete localParam.UpType
        ssoParam = null
      }
      this.execLocal(localParam, ssoParam, scripts)
    }, () => {
      this.execError()
    })
  }
  execSso = (ssoParam, scripts) => {
    Api.getLocalConfig(ssoParam).then(res => {
      if (!res.status) {
        notification.warning({
          top: 92,
          message: res.message,
          duration: 5
        })
        this.execWarning()
        this.setState({}, () => {
          if (scripts.length === 0) {
            this.next()
          } else {
            this.loopRequest(scripts)
          }
        })
      } else {
        if (scripts.length === 0) {
          this.next()
        } else {
          this.loopRequest(scripts)
        }
      }
    }, () => {
      this.execError()
    })
  }
  execLocal = (localParam, ssoParam, scripts) => {
    Api.getLocalConfig(localParam).then(res => {
      if (!res.status) {
        notification.warning({
          top: 92,
          message: res.message,
          duration: 5
        })
        this.execWarning()
        this.setState({}, () => {
          if (scripts.length === 0) {
            this.next()
          } else {
            this.loopRequest(scripts)
          }
        })
      } else if (ssoParam) {
        this.execSso(ssoParam, scripts)
      } else {
        if (scripts.length === 0) {
          this.next()
        } else {
          this.loopRequest(scripts)
        }
      }
    }, () => {
      this.execError()
    })
  }
  execWarning = () => {
    const { version } = this.state
    if (!version) return
    this.setState({version: {...version, warning: true}})
  }
  execError = () => {
    const { version } = this.state
    if (!version) return
    this.setState({error: true, versions: this.state.versions.map(item => {
      if (version.id === item.id) {
        item.status = 'error'
      }
      return item
    })})
  }
  next = () => {
    const { version, versions } = this.state
    if (!version || !versions) return
    let sql = `declare @Vid nvarchar(50) set @Vid='' select top 1 @Vid=id from sVersionDetail_Local where BID='${version.BID}' and Status =10 if @Vid='' begin delete sVersion_Local where id ='${version.BID}'  delete sVersionDetail_Local where bid ='${version.BID}' end else begin  update sVersion_Local set deleted=1,Modifydate=getdate(),ModifyUserID=@UserID@ where id ='${version.BID}' end`
    let param = {
      func: 'sPC_TableData_InUpDe',
      exec_type: 'y',
      ID: version.BID
    }
    param.LText = Utils.formatOptions(sql)
    param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
    param.secretkey = Utils.encrypt('', param.timestamp)
    Api.getLocalConfig(param).then(response => {
      if (!response.status) {
        notification.warning({
          top: 92,
          message: response.message,
          duration: 5
        })
        return
      }
    })
    let nextver = versions[version.index + 1]
    let _versions = versions.map(item => {
      if (version.id === item.id) {
        item.status = 'done'
        item.warning = version.warning === true
      }
      return item
    })
    if (nextver) {
      this.setState({
        version: nextver,
        versions: _versions
      }, () => {
        this.queryScript()
      })
    } else {
      this.setState({
        version: null,
        versions: _versions
      })
      notification.success({
        top: 92,
        message: '升级已完成。',
        duration: 3
      })
    }
  }
  stop = () => {
    this.setState({
      version: null,
      versions: null,
      visible: false,
      error: false
    })
  }
  skip = () => {
    const { version, versions } = this.state
    let nextver = versions[version.index + 1]
    this.setState({
      version: nextver,
      error: false
    }, () => {
      this.queryScript()
    })
  }
  reset = () => {
    const { version } = this.state
    this.setState({versions: this.state.versions.map(item => {
      if (version.id === item.id) {
        item.status = 'loading'
      }
      return item
    }), error: false}, () => {
      this.queryScript()
    })
  }
  render () {
    const { visible, versions, error, version } = this.state
    return (
      <>
        <div style={{padding: '5px 25px'}} onClick={this.verup}>版本升级</div>
        <Modal
          wrapClassName="version-up-modal"
          title="应用升级"
          visible={visible}
          width={800}
          closable={false}
          maskClosable={false}
          footer={[
            error && version && versions && versions.length > (version.index + 1) ? <Button key="close" onClick={this.skip}>跳过</Button> : null,
            error && version ? <Button key="close" onClick={this.reset}>重新执行</Button> : null,
            <Button key="close" onClick={this.stop}>关闭</Button>,
          ]}
          destroyOnClose
        >
          {versions ? <Timeline>
            {versions.map(item => {
              let icon = <Icon type="clock-circle-o" style={{ fontSize: '16px' }} />
              if (item.status === 'loading') {
                icon = <Icon type="sync" spin style={{ fontSize: '16px' }} />
              } else if (item.status === 'done') {
                if (item.warning) {
                  icon = <Icon type="warning" style={{ fontSize: '16px', color: 'orange' }}/>
                } else {
                  icon = <Icon type="check-circle" style={{ fontSize: '16px', color: '#52c41a' }} />
                }
              }
              return (
                <Timeline.Item key={item.id} dot={icon}>{item.ProgramName}</Timeline.Item>
              )
            })}
          </Timeline> : null}
        </Modal>
      </>
    )
  }
}
export default DataSource
src/components/header/versions/index.scss
New file
@@ -0,0 +1,31 @@
.version-up-modal {
  .ant-modal-body {
    padding: 24px 50px;
    min-height: 200px;
    max-height: calc(100vh - 210px);
    overflow-y: auto;
    .ant-timeline-item-content {
      height: 21px;
      white-space: nowrap;
      overflow: hidden;
      text-overflow: ellipsis;
    }
    .ant-timeline-item-head-custom {
      padding: 1px;
    }
  }
  .ant-modal-body::-webkit-scrollbar {
    width: 7px;
  }
  .ant-modal-body::-webkit-scrollbar-thumb {
    border-radius: 5px;
    box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.13);
    background: rgba(0, 0, 0, 0.13);
  }
  .ant-modal-body::-webkit-scrollbar-track {
    box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.05);
    border-radius: 3px;
    border: 1px solid rgba(0, 0, 0, 0.07);
    background: rgba(0, 0, 0, 0);
  }
}
src/components/header/versions/settingform/index.jsx
New file
@@ -0,0 +1,118 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import { Form, Row, Col, Input, InputNumber, Tooltip, Icon, Radio } from 'antd'
import './index.scss'
class SettingForm extends Component {
  static propTpyes = {
    dict: PropTypes.object,      // 字典项
    wrap: PropTypes.object,      // 数据源配置
    inputSubmit: PropTypes.func  // 回车事件
  }
  state = {}
  handleConfirm = () => {
    // 表单提交时检查输入值是否正确
    return new Promise((resolve, reject) => {
      this.props.form.validateFieldsAndScroll((err, values) => {
        if (!err) {
          resolve(values)
        } else {
          reject(err)
        }
      })
    })
  }
  handleSubmit = (e) => {
    e.preventDefault()
    if (this.props.inputSubmit) {
      this.props.inputSubmit()
    }
  }
  render() {
    const { wrap } = this.props
    const { getFieldDecorator } = this.props.form
    const formItemLayout = {
      labelCol: {
        xs: { span: 24 },
        sm: { span: 8 }
      },
      wrapperCol: {
        xs: { span: 24 },
        sm: { span: 16 }
      }
    }
    return (
      <div className="model-menu-setting-form">
        <Form {...formItemLayout}>
          <Row gutter={24}>
            <Col span={12}>
              <Form.Item label="导航栏名称">
                {getFieldDecorator('name', {
                  initialValue: wrap.name,
                  rules: [
                    {
                      required: true,
                      message: this.props.dict['form.required.input'] + '导航栏名称!'
                    }
                  ]
                })(<Input placeholder={''} autoComplete="off" onPressEnter={this.handleSubmit} />)}
              </Form.Item>
            </Col>
            <Col span={12}>
              <Form.Item label="菜单参数">
                {getFieldDecorator('MenuNo', {
                  initialValue: wrap.MenuNo,
                  rules: [
                    {
                      required: true,
                      message: this.props.dict['form.required.input'] + '菜单参数!'
                    }
                  ]
                })(<Input placeholder={''} autoComplete="off" onPressEnter={this.handleSubmit} />)}
              </Form.Item>
            </Col>
            <Col span={12}>
              <Form.Item label={
                <Tooltip placement="topLeft" title="选择静态值,无需配置数据源。">
                  <Icon type="question-circle" />
                  数据来源
                </Tooltip>
              }>
                {getFieldDecorator('datatype', {
                  initialValue: wrap.datatype || 'static'
                })(
                  <Radio.Group>
                    <Radio value="dynamic">动态</Radio>
                    <Radio value="static">静态</Radio>
                  </Radio.Group>
                )}
              </Form.Item>
            </Col>
            <Col span={12}>
              <Form.Item label="高度">
                {getFieldDecorator('height', {
                  initialValue: wrap.height || 50,
                  rules: [
                    {
                      required: true,
                      message: this.props.dict['form.required.input'] + '高度!'
                    }
                  ]
                })(<InputNumber min={30} max={200} precision={0} onPressEnter={this.handleSubmit} />)}
              </Form.Item>
            </Col>
          </Row>
        </Form>
      </div>
    )
  }
}
export default Form.create()(SettingForm)
src/components/header/versions/settingform/index.scss
New file
@@ -0,0 +1,11 @@
.model-menu-setting-form {
  position: relative;
  .anticon-question-circle {
    color: #c49f47;
    margin-right: 3px;
  }
  .ant-input-number {
    width: 100%;
  }
}
src/menu/components/card/cardcellcomponent/formconfig.jsx
@@ -386,6 +386,14 @@
    //   options: appMenus
    // },
    {
      type: 'select',
      key: 'linkurl',
      label: '链接地址',
      initVal: card.linkurl || '',
      required: true,
      options: []
    },
    {
      type: 'radio',
      key: 'joint',
      label: Formdict['model.form.paramJoint'],
@@ -398,14 +406,6 @@
        value: 'false',
        text: Formdict['model.false']
      }]
    },
    {
      type: 'select',
      key: 'linkurl',
      label: '链接地址',
      initVal: card.linkurl || '',
      required: true,
      options: []
    },
    {
      type: 'textarea',
src/menu/components/table/normal-table/index.jsx
@@ -56,8 +56,7 @@
        width: card.width || 24,
        search: [
          { origin: true, uuid: Utils.getuuid(), label: 'label', type: 'text', match: 'like' },
          { origin: true, uuid: Utils.getuuid(), label: 'label', type: 'select', match: 'equal' },
          { origin: true, uuid: Utils.getuuid(), label: 'label', type: 'date', match: 'greater' }
          { origin: true, uuid: Utils.getuuid(), label: 'label', type: 'select', match: 'equal' }
        ],
        action: [
          { origin: true, uuid: Utils.getuuid(), label: '添加', intertype: 'system', OpenType: 'pop', icon: 'plus', class: 'green', style: {color: 'rgb(255, 255, 255)', background: 'rgb(38, 194, 129)', marginRight: '15px'} },
src/menu/pastecontroller/index.jsx
@@ -51,9 +51,7 @@
      item.uuid = MenuUtils.getuuid()
      item.setting.name = item.setting.name + MenuUtils.getdataName().toUpperCase().substr(-4)
      item.name = item.setting.name
      if (appType !== 'mob') {
        item.components = item.components.filter(cell => cell.type !== 'menubar')
      }
      item.components = item.components.map(cell => {
        cell.floor = item.floor
        cell.tabId = item.tabId || ''
src/pc/components/login/normal-login/index.scss
@@ -110,6 +110,8 @@
        left: 0;
        right: 0;
        bottom: 0;
        width: auto!important;
        height: auto!important;
        canvas {
          width: 100%!important;
          height: 100%!important;
src/pc/createview/index.jsx
@@ -29,12 +29,37 @@
  verifySubmit = () => {
    this.verifyRef.handleConfirm().then(res => {
      let parMenuId = sessionStorage.getItem('kei_no') + sessionStorage.getItem('typename') + sessionStorage.getItem('lang')
      let menuId = Utils.getuuid()
      if (res.MenuId) {
        let appMenus = sessionStorage.getItem('appMenus')
        if (appMenus) {
          try {
            appMenus = JSON.parse(appMenus)
          } catch (e) {
            appMenus = []
          }
        } else {
          appMenus = []
        }
        if (appMenus.findIndex(item => item.MenuID === res.MenuId) > -1) {
          notification.warning({
            top: 92,
            message: '当前菜单已存在!',
            duration: 5
          })
          return
        }
        menuId = res.MenuId
      }
      this.setState({
        loading: true
      })
      let parMenuId = sessionStorage.getItem('kei_no') + sessionStorage.getItem('typename') + sessionStorage.getItem('lang')
      let menuId = Utils.getuuid()
      let config = {
        version: 1.0,
        uuid: menuId,
src/pc/createview/settingform/index.jsx
@@ -1,6 +1,6 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import { Form, Row, Col, Select, Input } from 'antd'
import { Form, Row, Col, Select, Input, Tooltip, Icon } from 'antd'
import './index.scss'
@@ -86,6 +86,28 @@
            </Form.Item>
          </Col>
          <Col span={20}>
            <Form.Item label={
              <Tooltip placement="topLeft" title="自定义菜单ID值。">
                <Icon type="question-circle" style={{color: '#c49f47', marginRight: '3px'}}/>
                菜单ID
              </Tooltip>
            }>
              {getFieldDecorator('MenuId', {
                initialValue: '',
                rules: [{
                  pattern: /^[0-9a-zA-Z]*$/ig,
                  message: '菜单ID只允许包含数字或字母(大小写)'
                }, {
                  min: 20,
                  message: '菜单ID最短为20个字符'
                }, {
                  max: 40,
                  message: '菜单ID最长为40个字符'
                }]
              })(<Input placeholder="" autoComplete="off" />)}
            </Form.Item>
          </Col>
          <Col span={20}>
            <Form.Item label="复制菜单">
              {getFieldDecorator('copymenuId', {
                initialValue: ''
src/pc/createview/settingform/index.scss
@@ -1,11 +0,0 @@
.model-menu-setting-form {
  position: relative;
  .anticon-question-circle {
    color: #c49f47;
    margin-right: 3px;
  }
  .ant-input-number {
    width: 100%;
  }
}
src/tabviews/custom/components/table/normal-table/index.scss
@@ -1,5 +1,6 @@
.custom-normal-table {
  position: relative;
  background-color: #fff;
  .normal-header {
    margin-bottom: 10px;
src/tabviews/verupmanage/config.jsx
@@ -35,8 +35,8 @@
        ]
      }
    },
    {OpenType:"prompt",Ot:"notRequired",callbackFunc:"",position:"toolbar",sysInterface:"true",execSuccess:"grid",label:"更新版本",intertype:"outer",execError:"never",class:"primary",
      icon:"",interface:"http://cloud.mk9h.cn/webapi/dostars",innerFunc:"",uuid:"15926364942911efnal5pv6r92if2vr2",outerFunc:"s_app_version_upt"}
    // {OpenType:"prompt",Ot:"notRequired",callbackFunc:"",position:"toolbar",sysInterface:"true",execSuccess:"grid",label:"更新版本",intertype:"outer",execError:"never",class:"primary",
    //   icon:"",interface:"http://cloud.mk9h.cn/webapi/dostars",innerFunc:"",uuid:"15926364942911efnal5pv6r92if2vr2",outerFunc:"s_app_version_upt"}
  ],
  columns:[
    {label:'ID',field:'ID',type:'text',Align:'left',Hide:'true',IsSort:'true',Width:120,prefix:'',postfix:'',matchVal:'',color:'',fieldlength:50,uuid:'1581736658674f11dg01sqdneu8bbn2q'},
@@ -92,7 +92,7 @@
      tableType:'checkbox',
      interType:'inner',
      innerFunc:'',
      dataresource:'select * from sVersionDetail_Local where BID=@BID@ and  deleted=0 and  status=0',
      dataresource:'select * from sVersionDetail_Local where BID=@BID@ and deleted=0 and status=0',
      queryType:'query',
      primaryKey:'ID',
      order:'Sort',
src/templates/zshare/formconfig.jsx
@@ -2534,6 +2534,15 @@
      }]
    },
    {
      type: 'text',
      key: 'disableField',
      label: '禁用·字段',
      initVal: card.disableField || '',
      tooltip: '设置禁用字段,且字段值为true时,选项不可选。',
      required: false,
      readonly: false
    },
    {
      type: 'radio',
      key: 'multiple',
      label: '可多选',
src/templates/zshare/modalform/index.jsx
@@ -161,20 +161,20 @@
      if (resourceType === '0') {        // 自定义资源
        _options.push('options')
      } else if (resourceType === '1') { // 数据源
        _options.push('dataSource', 'valueField', 'valueText', 'orderBy', 'orderType', 'database')
        _options.push('dataSource', 'valueField', 'valueText', 'orderBy', 'orderType', 'disableField', 'database')
      }
    } else if (type === 'checkcard') {
      if (display === 'picture') {
        if (resourceType === '0') {        // 自定义资源
          _options.push('options', 'ratio')
        } else if (resourceType === '1') { // 数据源
          _options.push('dataSource', 'cardValField', 'urlField', 'orderBy', 'orderType', 'database', 'ratio')
          _options.push('dataSource', 'cardValField', 'urlField', 'orderBy', 'orderType', 'disableField', 'database', 'ratio')
        }
      } else {
        if (resourceType === '0') {        // 自定义资源
          _options.push('options', 'fields', 'backgroundColor')
        } else if (resourceType === '1') { // 数据源
          _options.push('dataSource', 'cardValField', 'fields', 'orderBy', 'orderType', 'database', 'backgroundColor')
          _options.push('dataSource', 'cardValField', 'fields', 'orderBy', 'orderType', 'disableField', 'database', 'backgroundColor')
        }
      }
src/views/login/index.scss
@@ -226,6 +226,8 @@
        left: 0;
        right: 0;
        bottom: 0;
        width: auto!important;
        height: auto!important;
        canvas {
          width: 100%!important;
          height: 100%!important;
src/views/menudesign/index.jsx
@@ -3,7 +3,7 @@
import { is, fromJS } from 'immutable'
import moment from 'moment'
import HTML5Backend from 'react-dnd-html5-backend'
import { ConfigProvider, notification, Modal, Collapse, Card, Switch, Button } from 'antd'
import { ConfigProvider, notification, Modal, Collapse, Card, Switch, Button, Typography } from 'antd'
import html2canvas from 'html2canvas'
import Api from '@/api'
@@ -21,6 +21,7 @@
const { Panel } = Collapse
const { confirm } = Modal
const { Paragraph } = Typography
const _locale = sessionStorage.getItem('lang') !== 'en-US' ? antdZhCN : antdEnUS
const MenuForm = asyncComponent(() => import('./menuform'))
@@ -958,6 +959,7 @@
                    /> : null}
                    {/* 表名添加 */}
                    {config ? <TableComponent config={config} updatetable={this.updateConfig}/> : null}
                    <Paragraph style={{padding: '15px 0px 0px 18px'}} copyable={{ text: MenuId }}>菜单ID</Paragraph>
                  </Panel>
                  {/* 组件添加 */}
                  <Panel header={dict['mob.component']} key="component">
src/views/mobdesign/index.jsx
@@ -5,7 +5,7 @@
import { is, fromJS } from 'immutable'
import moment from 'moment'
import HTML5Backend from 'react-dnd-html5-backend'
import { ConfigProvider, notification, Modal, Collapse, Switch, Button, message, Spin, Icon } from 'antd'
import { ConfigProvider, notification, Modal, Collapse, Switch, Button, message, Spin, Icon, Typography } from 'antd'
import Api from '@/api'
import Utils, { setGLOBFuncs } from '@/utils/utils.js'
@@ -21,6 +21,7 @@
const { Panel } = Collapse
const { confirm } = Modal
const { Paragraph } = Typography
const Header = asyncComponent(() => import('@/mob/header'))
const MenuForm = asyncComponent(() => import('./menuform'))
@@ -1328,6 +1329,7 @@
                    {config ? <UrlFieldComponent config={config} updateConfig={this.updateConfig}/> : null}
                    {/* 表名添加 */}
                    {config ? <TableComponent config={config} updatetable={this.updateConfig}/> : null}
                    <Paragraph style={{padding: '15px 0px 0px 18px'}} copyable={{ text: MenuId }}>菜单ID</Paragraph>
                  </Panel>
                  {/* 组件添加 */}
                  <Panel header={dict['mob.component']} key="component">
src/views/pcdesign/index.jsx
@@ -5,7 +5,7 @@
import { is, fromJS } from 'immutable'
import moment from 'moment'
import HTML5Backend from 'react-dnd-html5-backend'
import { ConfigProvider, notification, Modal, Collapse, Switch, Button, Icon, message, Spin } from 'antd'
import { ConfigProvider, notification, Modal, Collapse, Switch, Button, Icon, message, Spin, Typography } from 'antd'
import Api from '@/api'
import Utils, { setGLOBFuncs } from '@/utils/utils.js'
@@ -21,6 +21,7 @@
const { Panel } = Collapse
const { confirm } = Modal
const { Paragraph } = Typography
const MenuForm = asyncComponent(() => import('./menuform'))
const Transfer = asyncComponent(() => import('@/pc/transfer'))
@@ -1566,6 +1567,7 @@
                    {config ? <UrlFieldComponent config={config} updateConfig={this.updateConfig}/> : null}
                    {/* 表名添加 */}
                    {config ? <TableComponent config={config} updatetable={this.updateConfig}/> : null}
                    <Paragraph style={{padding: '15px 0px 0px 18px'}} copyable={{ text: MenuId }}>菜单ID</Paragraph>
                  </Panel>
                  {/* 组件添加 */}
                  <Panel header={dict['mob.component']} key="component">