king
2020-10-05 6257816acce548a113081578140058cd99e83160
2020-10-05
22个文件已修改
1476 ■■■■ 已修改文件
src/components/header/index.jsx 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/actioncomponent/index.jsx 536 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/actioncomponent/verifyexcelin/customscript/index.jsx 5 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/bgcontroller/index.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/card/cardcomponent/index.jsx 129 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/card/cardcomponent/index.scss 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/card/cardcomponent/settingform/index.jsx 438 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/card/cardcomponent/settingform/index.scss 25 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/card/data-card/index.jsx 59 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/card/data-card/index.scss 5 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/card/data-card/wrapsetting/settingform/index.jsx 30 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/stylecontroller/index.jsx 66 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/stylecontroller/styleInput/index.jsx 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/mob/colorsketch/index.scss 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/mob/controller/index.jsx 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/mob/header/index.scss 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/formtabconfig/index.jsx 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/actioncomponent/index.jsx 58 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/actioncomponent/verifyexcelin/customscript/index.jsx 5 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/zshare/createfunc/index.jsx 23 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/utils.js 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/menudesign/index.jsx 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/header/index.jsx
@@ -740,9 +740,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/menu/actioncomponent/index.jsx
@@ -3,7 +3,6 @@
import {connect} from 'react-redux'
import { is, fromJS } from 'immutable'
import { Modal, notification, Button } from 'antd'
import moment from 'moment'
import Api from '@/api'
import options from '@/store/options.js'
@@ -39,7 +38,6 @@
    card: null,          // 编辑中元素
    formlist: null,      // 表单信息
    actionlist: null,    // 按钮组
    copying: false,      // 按钮复制中
    visible: false,      // 模态框控制
    profVisible: false   // 验证信息模态框
  }
@@ -267,15 +265,10 @@
  }
  /**
   * @description 搜索修改后提交保存
   * 1、去除系统默认搜索条件
   * 2、字段及提示文字重复校验
   * 3、更新下拉菜单可选集合
   * 4、下拉菜单数据源语法验证
   * @description 按钮修改后提交保存
   */
  handleSubmit = () => {
    const { config, menu } = this.props
    const { card } = this.state
    const { config } = this.props
    let _actionlist = fromJS(this.state.actionlist).toJS()
    this.actionFormRef.handleConfirm().then(btn => {
@@ -304,350 +297,11 @@
      }
      this.setState({
        copying: true
        actionlist: _actionlist,
        visible: false
      }, () => {
        this.props.updateaction({...config, action: _actionlist})
      })
      let copyActionId = '' // 按钮为复制时,记录当前按钮的Id,菜单取消保存时,删除复制按钮配置信息
      /**
       * @description 按钮保存校验
       * 1、检查按钮是否为表单或表单标签页,如前后一致,则复制其内容
       * 2、检查按钮是否为标签页,如前后一致,则复制标签页
       */
      new Promise(resolve => {
        if (
          !card.originCard ||
          (btn.OpenType === 'pop' && card.originCard.OpenType !== 'pop') ||
          (['tab', 'blank'].includes(btn.OpenType) && !['tab', 'blank'].includes(card.originCard.OpenType)) ||
          (btn.OpenType === 'popview' && (!btn.createTab || card.originCard.OpenType !== 'popview' || !card.originCard.linkTab))
        ) { // 按钮不是复制,或按钮前后类型不一致时,直接保存
          resolve('save')
        } else if (btn.OpenType === 'pop' || btn.OpenType === 'tab' || btn.OpenType === 'blank') {
          resolve('subconf')
        } else if (btn.OpenType === 'popview') {
          resolve('subtab')
        } else {
          resolve('save')
        }
      }).then(result => { // 查询原按钮配置信息
        if (result === 'save' || result === 'subtab') return result
        return Api.getSystemConfig({
          func: 'sPC_Get_LongParam',
          MenuID: card.originCard.uuid
        })
      }).then(result => { // 复制按钮配置信息,保存至新添加按钮
        if (result === 'save' || result === 'subtab') return result
        if (result.status && result.LongParam) {
          let _LongParam = ''
          // 解析配置
          if (result.LongParam) {
            try {
              _LongParam = JSON.parse(window.decodeURIComponent(window.atob(result.LongParam)))
            } catch (e) {
              console.warn('Parse Failure')
              _LongParam = ''
            }
          }
          let _temp = '' // 配置信息类型
          // 修改模态框标题名称
          if (btn.OpenType === 'pop' && _LongParam && _LongParam.type === 'Modal') {
            try {
              _LongParam.setting.title = btn.label
              _LongParam = window.btoa(window.encodeURIComponent(JSON.stringify(_LongParam)))
              _temp = 'Modal'
            } catch {
              console.warn('Stringify Failure')
              _LongParam = ''
              _temp = ''
            }
          } else if (['tab', 'blank'].includes(btn.OpenType) && _LongParam && _LongParam.type === 'FormTab') {
            try {
              _LongParam.action = _LongParam.action.map(_btn => {
                _btn.uuid = Utils.getuuid()
                return _btn
              })
              _LongParam.tabgroups.forEach(_groupId => {
                _LongParam[_groupId] = _LongParam[_groupId].map(_tab => {
                  _tab.uuid = Utils.getuuid()
                  return _tab
                })
              })
              _LongParam = window.btoa(window.encodeURIComponent(JSON.stringify(_LongParam)))
              _temp = 'FormTab'
            } catch {
              console.warn('Stringify Failure')
              _LongParam = ''
              _temp = ''
            }
          }
          if (!_temp) return 'save'
          let param = {
            func: 'sPC_ButtonParam_AddUpt',
            ParentID: menu.MenuID,
            MenuID: btn.uuid,
            MenuNo: menu.MenuNo,
            Template: _temp,
            MenuName: btn.label,
            PageParam: JSON.stringify({Template: _temp}),
            LongParam: _LongParam
          }
          return Api.getSystemConfig(param)
        } else {
          if (!result.status) {
            notification.warning({
              top: 92,
              message: result.message,
              duration: 5
            })
          }
          return 'save'
        }
      }).then(result => {
        if (result === 'save' || result === 'subtab') return result
        if (!result.status) {
          notification.warning({
            top: 92,
            message: result.message,
            duration: 5
          })
        } else {
          copyActionId = btn.uuid
        }
        return 'save'
      }).then(result => { // 查询原按钮关联标签信息
        if (result === 'save') return result
        return Api.getSystemConfig({
          func: 'sPC_Get_LongParam',
          MenuID: card.originCard.linkTab
        })
      }).then(result => { // 标签复制
        if (result === 'save') return result
        let _LongParam = '' // 标签配置信息
        if (!result.status) {
          notification.warning({
            top: 92,
            message: result.message,
            duration: 5
          })
        } else if (result.LongParam) {
          // 解析标签配置
          try {
            _LongParam = JSON.parse(window.decodeURIComponent(window.atob(result.LongParam)))
          } catch (e) {
            console.warn('Parse Failure')
            _LongParam = ''
          }
        }
        if (!_LongParam) {
          return 'save'
        } else {
          copyActionId = btn.linkTab
          return new Promise(resolve => {
            this.copytab(btn, _LongParam, resolve)
          })
        }
      }).then(() => {
        this.setState({
          actionlist: _actionlist,
          copying: false,
          visible: false
        }, () => {
          this.props.updateaction({...config, action: _actionlist}, copyActionId)
        })
      })
    })
  }
  /**
   * @description 标签复制
   * 1、保存按钮关联的新标签
   * 2、保存标签按钮信息
   * 3、保存新标签中按钮的子配置信息
   */
  copytab = (btn, _tab, _resolve) => {
    let _LongParam = ''
    _tab.uuid = btn.linkTab
    _tab.tabName = _tab.tabName + moment().format('YYYY-MM-DD HH:mm:ss')
    _tab.tabNo = _tab.tabNo + moment().format('YYYY-MM-DD HH:mm:ss')
    let param = {
      func: 'sPC_Tab_AddUpt',
      MenuID: _tab.uuid,
      MenuNo: _tab.tabNo,
      Template: _tab.Template,
      MenuName: _tab.tabName,
      Remark: _tab.Remark,
      PageParam: JSON.stringify({Template: _tab.Template}),
      Sort: 0
    }
    let _oriActions = []
    let btnParam = {
      func: 'sPC_Button_AddUpt',
      Type: 40,
      ParentID: _tab.uuid,
      MenuNo: _tab.tabNo,
      Template: _tab.Template,
      PageParam: '',
      LongParam: '',
      LText: ''
    }
    try {
      let _linkchange = {}
      btnParam.LText = []
      _tab.action = _tab.action.map((item, index) => {
        let uuid = Utils.getuuid()
        if (item.OpenType === 'pop') {
          _oriActions.push({
            prebtn: JSON.parse(JSON.stringify(item)),
            curuuid: uuid,
            Template: 'Modal'
          })
        } else if (item.OpenType === 'popview') {
          _linkchange[item.linkTab] = Utils.getuuid()
          item.linkTab = _linkchange[item.linkTab]
        }
        item.uuid = uuid
        btnParam.LText.push(`select '${item.uuid}' as menuid, '${item.label}' as menuname, '${(index + 1) * 10}' as Sort`)
        return item
      })
      if (_tab.funcs && _tab.funcs.length > 0) {
        _tab.funcs = _tab.funcs.map(item => {
          if (item.type === 'tab') {
            item.linkTab = _linkchange[item.linkTab]
            item.menuNo = ''
            item.subfuncs = []
          }
          return item
        })
      }
      btnParam.LText = btnParam.LText.join(' union all ')
      btnParam.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
      btnParam.LText = Utils.formatOptions(btnParam.LText)
      btnParam.secretkey = Utils.encrypt(btnParam.LText, btnParam.timestamp)
      _LongParam = window.btoa(window.encodeURIComponent(JSON.stringify(_tab)))
    } catch {
      console.warn('Stringify Failure')
      _LongParam = ''
      _resolve('save')
      return
    }
    param.LongParam = _LongParam
    new Promise(resolve => {
      Api.getSystemConfig(param).then(response => {
        if (response.status) {
          resolve(true)
        } else {
          notification.warning({
            top: 92,
            message: response.message,
            duration: 5
          })
          resolve(false)
        }
      })
    }).then(result => {
      if (!result) return result
      if (!btnParam.LText) return true
      return Api.getSystemConfig(btnParam)
    }).then(result => {
      if (result === false || result === true) return result
      if (result.status) {
        return true
      } else {
        notification.warning({
          top: 92,
          message: result.message,
          duration: 5
        })
        return false
      }
    }).then(result => {
      if (!result) return result
      if (_oriActions.length === 0) return true
      let deffers = _oriActions.map(item => {
        return new Promise(resolve => {
          Api.getSystemConfig({
            func: 'sPC_Get_LongParam',
            MenuID: item.prebtn.uuid
          }).then(response => {
            if (!response.status || !response.LongParam) {
              resolve(response)
            } else {
              let _param = {
                func: 'sPC_ButtonParam_AddUpt',
                ParentID: _tab.uuid,
                MenuID: item.curuuid,
                MenuNo: _tab.tabNo,
                Template: item.Template,
                MenuName: item.prebtn.label,
                PageParam: JSON.stringify({Template: item.Template}),
                LongParam: response.LongParam
              }
              Api.getSystemConfig(_param).then(resp => {
                resolve(resp)
              })
            }
          })
        })
      })
      return Promise.all(deffers)
    }).then(result => {
      let error = ''
      if (typeof(result) === 'object') {
        result.forEach(resul => {
          if (!resul.status && !error) {
            error = resul
          }
        })
      }
      if (error) {
        notification.warning({
          top: 92,
          message: error.message,
          duration: 5
        })
      }
      _resolve('save')
    })
  }
@@ -666,15 +320,19 @@
        _actionlist = _actionlist.filter(item => item.uuid !== card.uuid)
        let delcard = {
          type: 'action',
          card: card
        let delButtons = sessionStorage.getItem('delButtons')
        try {
          delButtons = JSON.parse(delButtons)
          delButtons.push(card.uuid)
        } catch {
          delButtons = [card.uuid]
        }
        sessionStorage.setItem('delButtons', JSON.stringify(delButtons))
        _this.setState({
          actionlist: _actionlist
        }, () => {
          _this.props.updateaction({...config, action: _actionlist}, '', delcard)
          _this.props.updateaction({...config, action: _actionlist})
        })
      },
      onCancel() {}
@@ -723,39 +381,13 @@
   * @description 创建按钮存储过程
   */
  creatFunc = () => {
    const { config, menu } = this.props
    const { menu } = this.props
    let _config = fromJS(this.props.config).toJS()
    this.actionFormRef.handleConfirm().then(res => {
      let btn = res         // 按钮信息
      let newLText = ''     // 创建存储过程sql
      let DelText = ''      // 删除存储过程sql
      let _actionlist = fromJS(this.state.actionlist).toJS()
      _actionlist = _actionlist.filter(item => !item.origin || item.uuid === btn.uuid)
      let labelrepet = false
      _actionlist = _actionlist.map(item => {
        if (item.uuid !== btn.uuid && item.label === btn.label) {
          labelrepet = true
        }
        if (item.uuid === btn.uuid) {
          return btn
        } else {
          return item
        }
      })
      if (labelrepet) {
        notification.warning({
          top: 92,
          message: this.state.dict['model.name.exist'] + ' !',
          duration: 5
        })
        return
      }
      // 创建存储过程,必须填写内部函数名
      if (btn.intertype !== 'inner') {
@@ -767,102 +399,50 @@
        return
      }
      new Promise(resolve => {
        // 弹窗(表单)类按钮,先获取按钮配置信息,如果尚未配置按钮则会报错并终止。
        // 获取信息后生成删除和创建存储过程的语句
        if (btn.OpenType === 'pop') {
          Api.getSystemConfig({
            func: 'sPC_Get_LongParam',
            MenuID: btn.uuid
          }).then(res => {
            let _LongParam = ''
            if (res.status && res.LongParam) {
              try {
                _LongParam = JSON.parse(window.decodeURIComponent(window.atob(res.LongParam)))
              } catch (e) {
                console.warn('Parse Failure')
                _LongParam = ''
              }
            }
            if (_LongParam) {
              let fields = []
              if (_LongParam.groups.length > 0) {
                _LongParam.groups.forEach(group => {
                  fields = [...fields, ...group.sublist]
                })
              } else {
                fields = _LongParam.fields
              }
              let _param = {
                funcName: btn.innerFunc,
                name: _config.setting.tableName || '',
                fields: fields,
                menuNo: menu.MenuNo
              }
              newLText = Utils.formatOptions(DevUtils.getfunc(_param, btn, menu, _config))
              DelText = Utils.formatOptions(DevUtils.dropfunc(btn.innerFunc))
              resolve(true)
            } else {
              notification.warning({
                top: 92,
                message: '弹窗(表单)按钮,请先配置表单信息!',
                duration: 5
              })
              resolve(false)
            }
      if (btn.OpenType === 'pop') {
        let fields = []
        if (btn.groups.length > 0) {
          btn.groups.forEach(group => {
            fields = [...fields, ...group.sublist]
          })
        } else if (btn.OpenType === 'excelIn') {
          if (btn.verify && btn.verify.sheet && btn.verify.columns && btn.verify.columns.length > 0) {
            let _param = {
              funcName: btn.innerFunc,
              menuNo: menu.MenuNo
            }
            newLText = Utils.formatOptions(DevUtils.getexcelInfunc(_param, btn, menu))
            DelText = Utils.formatOptions(DevUtils.dropfunc(btn.innerFunc))
            resolve(true)
          } else {
            notification.warning({
              top: 92,
              message: '请完善导入Excel验证信息!',
              duration: 5
            })
            resolve(false)
          }
        } else if (btn.OpenType === 'excelOut') {
          let _param = {
            innerFunc: btn.innerFunc
          }
          newLText = Utils.formatOptions(DevUtils.getTableFunc(_param, menu, _config)) // 创建存储过程sql
          DelText = Utils.formatOptions(DevUtils.dropfunc(btn.innerFunc))
          resolve(true)
        } else {
          let _param = {
            funcName: btn.innerFunc,
            name: _config.setting.tableName || '',
            fields: '',
            menuNo: menu.MenuNo
          }
          newLText = Utils.formatOptions(DevUtils.getfunc(_param, btn, menu, _config))
          DelText = Utils.formatOptions(DevUtils.dropfunc(btn.innerFunc))
          resolve(true)
          fields = btn.fields
        }
      }).then(res => {
        if (!res) return
        this.refs.btnCreatFunc.exec(btn.innerFunc, newLText, DelText).then(result => {
          if (result !== 'success') return
        let _param = {
          funcName: btn.innerFunc,
          name: _config.setting.tableName || '',
          fields: fields,
          menuNo: menu.MenuNo
        }
        newLText = Utils.formatOptions(DevUtils.getfunc(_param, btn, menu, _config))
        DelText = Utils.formatOptions(DevUtils.dropfunc(btn.innerFunc))
      } else if (btn.OpenType === 'excelIn') {
        let _param = {
          funcName: btn.innerFunc,
          menuNo: menu.MenuNo
        }
        newLText = Utils.formatOptions(DevUtils.getexcelInfunc(_param, btn, menu))
        DelText = Utils.formatOptions(DevUtils.dropfunc(btn.innerFunc))
      } else if (btn.OpenType === 'excelOut') {
        let _param = {
          innerFunc: btn.innerFunc
        }
          this.setState({
            actionlist: _actionlist
          }, () => {
            this.props.updateaction({...config, action: _actionlist})
          })
        })
      })
        newLText = Utils.formatOptions(DevUtils.getTableFunc(_param, menu, _config)) // 创建存储过程sql
        DelText = Utils.formatOptions(DevUtils.dropfunc(btn.innerFunc))
      } else {
        let _param = {
          funcName: btn.innerFunc,
          name: _config.setting.tableName || '',
          fields: '',
          menuNo: menu.MenuNo
        }
        newLText = Utils.formatOptions(DevUtils.getfunc(_param, btn, menu, _config))
        DelText = Utils.formatOptions(DevUtils.dropfunc(btn.innerFunc))
      }
      this.refs.btnCreatFunc.exec(btn.innerFunc, newLText, DelText)
    })
  }
@@ -870,7 +450,7 @@
   * @description 按钮双击触发子配置
   */
  btnDoubleClick = (element) => {
    if (!element.origin && (element.OpenType === 'pop' || element.OpenType === 'popview' || element.OpenType === 'blank' || element.OpenType === 'tab')) {
    if (element.OpenType === 'pop' || element.OpenType === 'popview') {
      this.props.setSubConfig(element)
    } else {
      notification.warning({
@@ -883,7 +463,7 @@
  render() {
    const { config, plus } = this.props
    const { actionlist, visible, card, dict, copying, profVisible } = this.state
    const { actionlist, visible, card, dict, profVisible } = this.state
    return (
      <div className="model-menu-action-list">
@@ -904,9 +484,9 @@
          maskClosable={false}
          onCancel={this.editModalCancel}
          footer={[
            card && !card.copyType ? <CreateFunc key="create" dict={dict} ref="btnCreatFunc" trigger={this.creatFunc}/> : null,
            <CreateFunc key="create" dict={dict} ref="btnCreatFunc" trigger={this.creatFunc}/>,
            <Button key="cancel" onClick={this.editModalCancel}>{dict['model.cancel']}</Button>,
            <Button key="confirm" type="primary" loading={copying} onClick={this.handleSubmit}>{dict['model.confirm']}</Button>
            <Button key="confirm" type="primary" onClick={this.handleSubmit}>{dict['model.confirm']}</Button>
          ]}
          destroyOnClose
        >
src/menu/actioncomponent/verifyexcelin/customscript/index.jsx
@@ -202,7 +202,10 @@
        fields = fields + ','
      }
      _value = `Insert into ${btn.sheet} (${fields}createuserid,createuser,createstaff,bid)\nSelect ${fields}@userid@,@username,@fullname,@BID@ From @${btn.sheet}`
      let database = btn.sheet.match(/(.*)\.(.*)\./ig) || ''
      let sheet = btn.sheet.replace(/(.*)\.(.*)\./ig, '')
      _value = `Insert into ${database}${sheet} (${fields}createuserid,createuser,createstaff,bid)\nSelect ${fields}@userid@,@username,@fullname,@BID@ From @${sheet}`
    } else {
      _value = value
    }
src/menu/bgcontroller/index.jsx
@@ -73,7 +73,7 @@
    if (/^http|^\/\//.test(val)) {
      val = `url(${val})`
    } else if (/^#|,/ig.test(val)) {
    } else if (/,/ig.test(val) && !/^(radial-gradient|linear-gradient)/ig.test(val)) {
      val = `linear-gradient(${val})`
    }
src/menu/components/card/cardcomponent/index.jsx
@@ -7,6 +7,7 @@
import zhCN from '@/locales/zh-CN/model.js'
import enUS from '@/locales/en-US/model.js'
// import { getCardCellForm } from './formconfig'
import SettingForm from './settingform'
import Utils from '@/utils/utils.js'
import MKEmitter from '@/utils/events.js'
@@ -19,15 +20,17 @@
  static propTpyes = {
    config: PropTypes.object,        // 菜单配置信息
    card: PropTypes.object,          // 卡片配置信息
    deleteElement: PropTypes.func,   // 卡片删除
    updateElement: PropTypes.func    // 菜单配置更新
  }
  state = {
    dict: localStorage.getItem('lang') !== 'en-US' ? zhCN : enUS,
    card: null,          // 卡片信息,包括正反面
    formlist: null,      // 设置表单信息
    elements: null,      // 编辑组
    visible: false,      // 模态框控制
    card: null,            // 卡片信息,包括正反面
    formlist: null,        // 设置表单信息
    elements: null,        // 编辑组
    visible: false,        // 模态框控制
    settingVisible: false,
    side: 'front'
  }
@@ -45,6 +48,7 @@
  componentDidMount () {
    MKEmitter.addListener('cardAddElement', this.cardAddElement)
    MKEmitter.addListener('submitStyle', this.getStyle)
  }
  shouldComponentUpdate (nextProps, nextState) {
@@ -59,6 +63,31 @@
      return
    }
    MKEmitter.removeListener('cardAddElement', this.cardAddElement)
    MKEmitter.removeListener('submitStyle', this.getStyle)
  }
  getStyle = (comIds, style) => {
    const { config } = this.props
    const { card, side } = this.state
    if (comIds.length !== 2 || comIds[0] !== config.uuid || comIds[1] !== card.uuid) return
    let _card = fromJS(card).toJS()
    if (side === 'back') {
      _card.backStyle = style
    } else {
      _card.style = style
    }
    this.setState({
      card: _card
    })
    this.props.updateElement(_card)
  }
  updateCard = (cell) => {
  }
  cardAddElement = (cardId, element) => {
@@ -206,6 +235,7 @@
    newcard.uuid = Utils.getuuid()
    newcard.focus = true
    
    newcard.eleType = 'button'
    newcard.label = 'button'
    newcard.sqlType = ''
    newcard.Ot = 'requiredSgl'
@@ -226,58 +256,83 @@
  }
  changeStyle = () => {
    const { card } = this.state
    const { config } = this.props
    const { card, side } = this.state
    MKEmitter.emit('changeStyle', [card.uuid], ['font', 'background', 'border'], {})
    let _style = null
    let options = ['height', 'background', 'border', 'padding', 'margin']
    if (side === 'front') {
      _style = card.style ? fromJS(card.style).toJS() : {}
    } else if (side === 'back') {
      _style = card.backStyle ? fromJS(card.backStyle).toJS() : {}
      options = ['background', 'border', 'padding', 'margin']
    }
    MKEmitter.emit('changeStyle', [config.uuid, card.uuid], options, _style)
  }
  settingSubmit = () => {
    const { card, side } = this.state
    this.settingRef.handleConfirm().then(res => {
      this.setState({
        settingVisible: false,
        card: {...card, setting: res}
      })
      if (side === 'back' && res.type === 'simple') {
        this.setState({
          side: 'front',
          elements: fromJS(card.elements).toJS()
        })
      }
      this.props.updateElement({...card, setting: res})
    })
  }
  render() {
    // const { config } = this.props
    const { card, elements } = this.state
    const { card, elements, side, settingVisible, dict } = this.state
    let _style = card.style
    if (side === 'back') {
      _style = {...card.backStyle, height: card.style.height}
    }
    return (
      <div className={'ant-col card-item ant-col-' + (card.setting.width || 6)} style={{height: card.setting.height ? card.setting.height + 'px' : 'auto'}}>
      <div className={'ant-col card-item ant-col-' + (card.setting.width || 6)} style={_style}>
        <CardCellComponent config={card} elements={elements} updateElement={this.updateComponent}/>
        <div className="card-control">
          <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={
            <div className="mk-popover-control">
              <Icon className="plus" title="添加元素" onClick={this.addElement} type="plus" />
              <Icon className="plus" title="添加按钮" onClick={this.addButton} type="plus-square" />
              <Icon className="edit" type="edit" onClick={() => this.setState({settingVisible: true})} />
              <Icon className="style" title="调整样式" onClick={this.changeStyle} type="font-colors" />
              <Switch size="small" onClick={this.changeSide} defaultChecked />
              {card.setting.type === 'multi' ? <Switch size="small" onClick={this.changeSide} defaultChecked /> : null}
            </div>
          } trigger="hover">
            <Icon type="tool" />
          </Popover>
        </div>
        <Modal
          wrapClassName="popview-modal"
          title={'卡片设置'}
          visible={settingVisible}
          width={700}
          maskClosable={false}
          okText={dict['model.submit']}
          onOk={this.settingSubmit}
          onCancel={() => { this.setState({ settingVisible: false }) }}
          destroyOnClose
        >
          <SettingForm
            dict={dict}
            setting={card.setting}
            wrappedComponentRef={(inst) => this.settingRef = inst}
          />
        </Modal>
      </div>
      // <div className="model-menu-card-cell-list">
      //   <DragElement
      //     list={elements}
      //     handleList={this.handleList}
      //     handleMenu={this.handleElement}
      //     deleteMenu={this.deleteElement}
      //   />
      //   {/* 编辑按钮:复制、编辑 */}
      //   <Modal
      //     title={'编辑元素'}
      //     visible={visible}
      //     width={800}
      //     maskClosable={false}
      //     onCancel={this.editModalCancel}
      //     onOk={this.handleSubmit}
      //     destroyOnClose
      //   >
      //     <ElementForm
      //       dict={dict}
      //       card={card}
      //       formlist={this.state.formlist}
      //       inputSubmit={this.handleSubmit}
      //       config={config}
      //       wrappedComponentRef={(inst) => this.elementFormRef = inst}
      //     />
      //   </Modal>
      // </div>
    )
  }
}
src/menu/components/card/cardcomponent/index.scss
@@ -1,25 +0,0 @@
.model-menu-card-cell-list {
  position: relative;
  .ant-form-item-label {
    .anticon-question-circle {
      color: #c49f47;
      position: absolute;
      left: 5px;
      top: 5px;
    }
  }
  .card-detail-row > .anticon-plus {
    color: #26C281;
    font-size: 16px;
    padding: 5px;
    cursor: pointer;
  }
  .card-cell:hover {
    box-shadow: 0px 0px 1px #d8d8d8;
  }
  .ant-slider {
    margin: 0px;
  }
}
src/menu/components/card/cardcomponent/settingform/index.jsx
@@ -1,346 +1,13 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import { fromJS } from 'immutable'
import { Form, Row, Col, Input, Select, Icon, Radio, Tooltip, InputNumber, notification } from 'antd'
import { Form, Row, Col, Radio, Tooltip, Icon, InputNumber } from 'antd'
import { formRule } from '@/utils/option.js'
import FileUpload from '@/tabviews/zshare/fileupload'
import ColorSketch from '@/mob/colorsketch'
import './index.scss'
const cardTypeOptions = {
  text: ['eleType', 'datatype', 'value', 'format', 'fontSize', 'fontWeight', 'width', 'height', 'color', 'align', 'padding', 'prefix', 'postfix'],
  number: ['eleType', 'datatype', 'value', 'format', 'fontSize', 'fontWeight', 'width', 'height', 'color', 'align', 'padding', 'prefix', 'postfix'],
  picture: ['eleType', 'datatype', 'width', 'lenWidRadio', 'radius', 'padding', 'url'],
  icon: ['eleType', 'icon', 'fontSize', 'width', 'height', 'color', 'align', 'padding', 'tooltip'],
  link: ['eleType', 'datatype', 'value', 'labelfield', 'fontSize', 'width', 'height', 'color', 'align', 'padding', 'prefix'],
  slider: ['eleType', 'field', 'width', 'color', 'padding', 'maxValue'],
  splitline: ['eleType', 'color', 'width', 'padding'],
}
class MainSearch extends Component {
class SettingForm extends Component {
  static propTpyes = {
    dict: PropTypes.object,      // 字典项
    config: PropTypes.object,    // 组件信息
    formlist: PropTypes.any,     // 表单信息
    card: PropTypes.any,         // 按钮信息
    inputSubmit: PropTypes.any   // 回车提交事件
  }
  state = {
    formlist: null,  // 表单信息
    eleType: '',
    datatype: ''
  }
  UNSAFE_componentWillMount () {
    const { card, config } = this.props
    let _options = this.getOptions(card.eleType, card.datatype)
    this.setState({
      eleType: card.eleType,
      datatype: card.datatype,
      formlist: this.props.formlist.map(item => {
        item.hidden = !_options.includes(item.key)
        if (item.key === 'field') {
          item.options = []
          config.columns.forEach(col => {
            if (!/^Nvarchar/ig.test(col.datatype) && (card.eleType === 'number' || card.eleType === 'slider')) {
              item.options.push({
                value: col.field,
                text: col.label
              })
            } else if (/^Nvarchar/ig.test(col.datatype) && card.eleType !== 'number' && card.eleType !== 'slider') {
              item.options.push({
                value: col.field,
                text: col.label
              })
            }
          })
        } else if (item.key === 'labelfield') {
          item.options = []
          config.columns.forEach(col => {
            if (/^Nvarchar/ig.test(col.datatype)) {
              item.options.push({
                value: col.field,
                text: col.label
              })
            }
          })
        }
        return item
      })
    })
  }
  getOptions = (eleType, datatype) => {
    let _options = fromJS(cardTypeOptions[eleType]).toJS() // 选项列表
    if (['text', 'number', 'picture', 'link'].includes(eleType)) {
      if (datatype === 'dynamic') {
        _options.push('field')
      }
    }
    return _options
  }
  /**
   * @description 下拉切换
   * 1、打开方式切换,重置可见表单和表单值
   * 2、显示位置切换,重置选择行
   * 3、切换标签类型,重置可选标签
   */
  selectChange = (key, value, option) => {
    const { config } = this.props
    const { datatype } = this.state
    if (key === 'eleType') {
      let _options = this.getOptions(value, datatype)
      let _formlist = this.state.formlist.map(item => {
        item.hidden = !_options.includes(item.key)
        if (item.key === 'field') {
          item.options = []
          config.columns.forEach(col => {
            if (!/^Nvarchar/ig.test(col.datatype) && (value === 'number' || value === 'slider')) {
              item.options.push({
                value: col.field,
                text: col.label
              })
            } else if (/^Nvarchar/ig.test(col.datatype) && value !== 'number' && value !== 'slider') {
              item.options.push({
                value: col.field,
                text: col.label
              })
            }
          })
        }
        return item
      })
      this.setState({
        eleType: value,
        formlist: _formlist
      }, () => {
        if (value === 'slider') {
          this.props.form.setFieldsValue({width: 24, color: '#1890ff'})
        } else if (value === 'splitline') {
          this.props.form.setFieldsValue({width: 24, color: '#e8e8e8'})
        }
      })
    } else if (key === 'field') {
      if (this.props.form.getFieldValue('value') !== undefined) {
        this.props.form.setFieldsValue({value: option.props.title})
      }
    }
  }
  onChange = (e, key) => {
    const { eleType } = this.state
    let value = e.target.value
    if (key === 'datatype') {
      let _options = this.getOptions(eleType, value)
      this.setState({
        datatype: value,
        formlist: this.state.formlist.map(item => {
          item.hidden = !_options.includes(item.key)
          return item
        })
      })
    }
  }
  handleSubmit = (e) => {
    e.preventDefault()
    if (this.props.inputSubmit) {
      this.props.inputSubmit()
    }
  }
  getFields() {
    const { getFieldDecorator } = this.props.form
    const fields = []
    this.state.formlist.forEach((item, index) => {
      if (item.hidden) return
      if (item.type === 'text') { // 文本搜索
        let rules = []
        if (item.key === 'padding') {
          rules = [{
            pattern: /^\d+px$|^\d+px\s\d+px$|^\d+px\s\d+px\s\d+px$|^\d+px\s\d+px\s\d+px\s\d+px$/ig,
            message: '请正确输入内边距!'
          }]
        }
        fields.push(
          <Col span={12} key={index}>
            <Form.Item label={item.tooltip ?
              <Tooltip placement="topLeft" overlayClassName={item.tooltipClass} title={item.tooltip}>
                <Icon type="question-circle" />
                {item.label}
              </Tooltip> : item.label
            }>
              {getFieldDecorator(item.key, {
                initialValue: item.initVal || '',
                rules: [
                  {
                    required: item.readonly ? false : !!item.required,
                    message: this.props.dict['form.required.input'] + item.label + '!'
                  },
                  {
                    max: formRule.input.max,
                    message: formRule.input.message
                  },
                  ...rules
                ]
              })(<Input placeholder="" autoComplete="off" disabled={item.readonly} onPressEnter={this.handleSubmit} />)}
            </Form.Item>
          </Col>
        )
      } else if (item.type === 'number') {
        fields.push(
          <Col span={12} key={index}>
            <Form.Item label={item.tooltip ?
              <Tooltip placement="topLeft" overlayClassName={item.tooltipClass} title={item.tooltip}>
                <Icon type="question-circle" />
                {item.label}
              </Tooltip> : item.label
            }>
              {getFieldDecorator(item.key, {
                initialValue: item.initVal,
                rules: [
                  {
                    required: item.readonly ? false : !!item.required,
                    message: this.props.dict['form.required.input'] + item.label + '!'
                  }
                ]
              })(<InputNumber min={item.min || 0} max={item.max || 10000} precision={item.precision || 0} />)}
            </Form.Item>
          </Col>
        )
      } else if (item.type === 'select') { // 下拉搜索
        fields.push(
          <Col span={12} key={index}>
            <Form.Item label={item.tooltip ?
              <Tooltip placement="topLeft" overlayClassName={item.tooltipClass} title={item.tooltip}>
                <Icon type="question-circle" />
                {item.label}
              </Tooltip> : item.label
            }>
              {getFieldDecorator(item.key, {
                initialValue: item.initVal || '',
                rules: [
                  {
                    required: !!item.required,
                    message: this.props.dict['form.required.select'] + item.label + '!'
                  }
                ]
              })(
                <Select
                  showSearch
                  filterOption={(input, option) => option.props.children[2].toLowerCase().indexOf(input.toLowerCase()) >= 0}
                  onChange={(value, option) => {this.selectChange(item.key, value, option)}}
                  getPopupContainer={() => document.getElementById('card-winter')}
                >
                  {item.options.map((option, index) =>
                    <Select.Option id={`${index}`} title={option.text} key={`${index}`} value={option.value}>
                      {item.key === 'icon' && option.value && <Icon type={option.value} />} {option.text}
                    </Select.Option>
                  )}
                </Select>
              )}
            </Form.Item>
          </Col>
        )
      } else if (item.type === 'radio') {
        fields.push(
          <Col span={12} key={index}>
            <Form.Item label={item.label}>
              {getFieldDecorator(item.key, {
                initialValue: item.initVal,
                rules: [
                  {
                    required: !!item.required,
                    message: this.props.dict['form.required.select'] + item.label + '!'
                  }
                ]
              })(
                <Radio.Group onChange={(e) => {this.onChange(e, item.key)}} disabled={item.readonly}>
                  {
                    item.options.map(option => {
                      return (
                        <Radio key={option.value} value={option.value}>{option.text}</Radio>
                      )
                    })
                  }
                </Radio.Group>
              )}
            </Form.Item>
          </Col>
        )
      } else if (item.type === 'color') {
        fields.push(
          <Col span={12} key={index} className="color-form">
            <Form.Item label={item.label}>
              {getFieldDecorator(item.key, {
                initialValue: item.initVal,
                rules: [
                  {
                    required: !!item.required,
                    message: this.props.dict['form.required.select'] + item.label + '!'
                  }
                ]
              })(
                <ColorSketch />
              )}
            </Form.Item>
          </Col>
        )
      } else if (item.type === 'file') {
        let filelist = []
        if (item.initVal) {
          filelist = [{
            uid: `1`,
            name: item.initVal.slice(item.initVal.lastIndexOf('/') + 1),
            status: 'done',
            url: item.initVal,
            origin: true
          }]
        }
        fields.push(
          <Col span={12} key={index}>
            <Form.Item label={item.label}>
              {getFieldDecorator(item.key, {
                initialValue: filelist,
                rules: [
                  {
                    required: !!item.required,
                    message: this.props.dict['form.required.select'] + item.label + '!'
                  }
                ]
              })(
                <FileUpload maxFile={item.maxfile} fileType={'text'} />
              )}
            </Form.Item>
          </Col>
        )
      }
    })
    return fields
    dict: PropTypes.object,    // 字典项
    setting: PropTypes.object, // 数据源配置
  }
  handleConfirm = () => {
@@ -348,32 +15,6 @@
    return new Promise((resolve, reject) => {
      this.props.form.validateFieldsAndScroll((err, values) => {
        if (!err) {
          values.uuid = this.props.card.uuid
          values.marks = this.props.card.marks || null
          if (values.url) {
            if (values.url.length > 0) {
              if (values.url[0].origin && values.url[0].url) {
                values.url = values.url[0].url
              } else if (!values.url[0].origin && values.url[0].status === 'done' && values.url[0].response) {
                values.url = values.url[0].response
              } else {
                values.url = ''
              }
            } else {
              values.url = ''
            }
          }
          if (values.eleType === 'picture' && values.datatype === 'static' && !values.url) {
            notification.warning({
              top: 92,
              message: '尚未添加图片或图片上传失败,请重新添加!',
              duration: 5
            })
            return
          }
          resolve(values)
        } else {
          reject(err)
@@ -383,22 +24,81 @@
  }
  render() {
    const { setting } = this.props
    const { getFieldDecorator } = this.props.form
    const formItemLayout = {
      labelCol: {
        xs: { span: 24 },
        sm: { span: 7 }
        sm: { span: 8 }
      },
      wrapperCol: {
        xs: { span: 24 },
        sm: { span: 17 }
        sm: { span: 16 }
      }
    }
    return (
      <Form {...formItemLayout} className="menu-card-detail-form" id="card-winter">
        <Row gutter={24}>{this.getFields()}</Row>
      </Form>
      <div className="model-menu-setting-form">
        <Form {...formItemLayout}>
          <Row gutter={24}>
            <Col span={12}>
              <Form.Item label={
                <Tooltip placement="topLeft" title="栅格布局,每行等分24份。">
                  <Icon type="question-circle" />
                  卡片宽度
                </Tooltip>
              }>
                {getFieldDecorator('width', {
                  initialValue: setting.width || 24,
                  rules: [
                    {
                      required: true,
                      message: this.props.dict['form.required.input'] + '宽度!'
                    }
                  ]
                })(<InputNumber min={1} max={24} precision={0} />)}
              </Form.Item>
            </Col>
            <Col span={12}>
              <Form.Item label={
                <Tooltip placement="topLeft" title="选择复式卡时,可配置鼠标悬浮时的显示信息。">
                  <Icon type="question-circle" />
                  卡片类型
                </Tooltip>
              }>
                {getFieldDecorator('type', {
                  initialValue: setting.type || 'simple'
                })(
                  <Radio.Group>
                    <Radio value="simple">单卡</Radio>
                    <Radio value="multi">复式卡</Radio>
                  </Radio.Group>
                )}
              </Form.Item>
            </Col>
            <Col span={12}>
              <Form.Item label={
                <Tooltip placement="topLeft" title="复式卡片鼠标悬浮信息的动画效果。">
                  <Icon type="question-circle" />
                  过渡效果
                </Tooltip>
              }>
                {getFieldDecorator('transform', {
                  initialValue: setting.transform || 'up'
                })(
                  <Radio.Group>
                    <Radio value="up">向上滑动</Radio>
                    <Radio value="down">向下滑动</Radio>
                  </Radio.Group>
                )}
              </Form.Item>
            </Col>
          </Row>
        </Form>
      </div>
    )
  }
}
export default Form.create()(MainSearch)
export default Form.create()(SettingForm)
src/menu/components/card/cardcomponent/settingform/index.scss
@@ -1,24 +1,11 @@
.menu-card-detail-form {
  min-height: 190px;
.model-menu-setting-form {
  position: relative;
  .anticon-question-circle {
    color: #c49f47;
    margin-right: 3px;
  }
  .ant-input-number {
    width: 100%;
  }
  .ant-form-item-label {
    .anticon-question-circle {
      color: #c49f47;
      margin-right: 5px;
    }
  }
  .ant-col {
    height: 65px;
  }
  .color-form {
    .ant-form-item-control {
      .color-sketch-block {
        position: relative;
        top: 7px;
      }
    }
  }
}
src/menu/components/card/data-card/index.jsx
@@ -2,7 +2,7 @@
import PropTypes from 'prop-types'
import {connect} from 'react-redux'
import { is, fromJS } from 'immutable'
import { Icon, Popover } from 'antd'
import { Icon, Popover, Modal } from 'antd'
import asyncComponent from '@/utils/asyncComponent'
import asyncIconComponent from '@/utils/asyncIconComponent'
@@ -16,6 +16,8 @@
const SettingComponent = asyncIconComponent(() => import('@/menu/datasource'))
const WrapComponent = asyncIconComponent(() => import('./wrapsetting'))
const CardComponent = asyncComponent(() => import('../cardcomponent'))
const { confirm } = Modal
class antvBarLineChart extends Component {
  static propTpyes = {
@@ -63,10 +65,11 @@
        style: { marginLeft: '8px', marginRight: '8px', marginTop: '8px', marginBottom: '8px' },
        columns: [],
        scripts: [],
        // action: [],
        subcards: [{
          uuid: Utils.getuuid(),
          setting: { width: 6 },
          setting: { width: 6, type: 'simple'},
          style: {borderWidth: '1px', borderColor: '#e8e8e8'},
          backStyle: {},
          elements: [],
          backElements: []
        }]
@@ -100,6 +103,9 @@
    MKEmitter.removeListener('submitStyle', this.getStyle)
  }
  /**
   * @description 卡片行外层信息更新(数据源,样式等)
   */
  updateComponent = (component) => {
    this.setState({
      card: component
@@ -111,6 +117,42 @@
    this.props.updateConfig(component)
  }
  /**
   * @description 单个卡片信息更新
   */
  updateCard = (cell) => {
    let card = fromJS(this.state.card).toJS()
    card.subcards = card.subcards.map(item => {
      if (item.uuid === cell.uuid) return cell
      return item
    })
    this.setState({card})
    this.props.updateConfig(card)
  }
  /**
   * @description 单个卡片信息更新
   */
  deleteCard = (cell) => {
    let card = fromJS(this.state.card).toJS()
    let _this = this
    confirm({
      content: '确定删除卡片吗?',
      onOk() {
        card.subcards = card.subcards.filter(item => item.uuid !== cell.uuid)
        _this.setState({card})
        _this.props.updateConfig(card)
      },
      onCancel() {}
    })
  }
  changeStyle = () => {
    const { card } = this.state
@@ -120,12 +162,15 @@
  getStyle = (comIds, style) => {
    const { card } = this.state
    if (comIds.length > 1 || comIds[0] !== card.uuid) return
    if (comIds.length !== 1 || comIds[0] !== card.uuid) return
    let _card = {...card, style}
    this.setState({
      card: {...card, style}
      card: _card
    })
    console.log(style)
    this.props.updateConfig(_card)
  }
  render() {
@@ -143,7 +188,7 @@
        } trigger="hover">
          <Icon type="tool" />
        </Popover>
        {card.subcards.map(subcard => (<CardComponent key={subcard.uuid} config={card} card={subcard} updateElement={this.updateComponent}/>))}
        {card.subcards.map(subcard => (<CardComponent key={subcard.uuid} config={card} card={subcard} updateElement={this.updateCard} deleteElement={this.deleteCard}/>))}
        {card.wrap.addable === 'true' ? <div className="card-add-button"><Icon type="plus" /></div> : null}
      </div>
    )
src/menu/components/card/data-card/index.scss
@@ -5,6 +5,8 @@
  background-position: center center;
  background-repeat: no-repeat;
  background-size: cover;
  border-style: solid;
  border-width: 0;
  
  .card-control {
    position: absolute;
@@ -30,7 +32,8 @@
    overflow-y: hidden;
    position: relative;
    min-height: 50px;
    border: 1px solid #e8e8e8;
    border-style: solid;
    border-width: 0;
  }
  
  .card-item:hover {
src/menu/components/card/data-card/wrapsetting/settingform/index.jsx
@@ -80,36 +80,6 @@
            </Col>
            <Col span={12}>
              <Form.Item label={
                <Tooltip placement="topLeft" title="高度为空时,使用自适应高度。">
                  <Icon type="question-circle" />
                  卡片高度
                </Tooltip>
              }>
                {getFieldDecorator('height', {
                  initialValue: wrap.height
                })(<InputNumber min={50} max={1000} precision={0} />)}
              </Form.Item>
            </Col>
            <Col span={12}>
              <Form.Item label={
                <Tooltip placement="topLeft" title="单个卡片所占的宽度,栅格布局,每行等分24份。">
                  <Icon type="question-circle" />
                  卡片宽度
                </Tooltip>
              }>
                {getFieldDecorator('cardWidth', {
                  initialValue: wrap.cardWidth || 6,
                  rules: [
                    {
                      required: true,
                      message: this.props.dict['form.required.input'] + '卡片宽度!'
                    }
                  ]
                })(<InputNumber min={1} max={24} precision={0} />)}
              </Form.Item>
            </Col>
            <Col span={12}>
              <Form.Item label={
                <Tooltip placement="topLeft" title="选择含有添加按钮时,请完善按钮配置信息。">
                  <Icon type="question-circle" />
                  添加按钮
src/menu/stylecontroller/index.jsx
@@ -184,19 +184,29 @@
    if (/^http|^\/\//.test(val)) {
      val = `url(${val})`
    } else if (/^#|,/ig.test(val)) {
    } else if (/,/ig.test(val) && !/^(radial-gradient|linear-gradient)/ig.test(val)) {
      val = `linear-gradient(${val})`
    }
    this.setState({backgroundImage: e.target.value})
    this.updateStyle({backgroundImage: val})
  }
  submitBorder = (val) => {
    let border = '0px'
    if (!/,\s0\)$/.test(val)) {
      border = `1px solid ${val}`
  changeBorderWidth = (val) => {
    this.updateStyle({borderWidth: val})
  }
  changeBorderColor = (val) => {
    this.updateStyle({borderColor: val})
  }
  changeHeight = (val) => {
    let _val = val
    if (_val === '0px') {
      _val = 'auto'
    }
    this.updateStyle({border: border})
    this.updateStyle({height: _val})
  }
  changeBorderRadius = (val) => {
@@ -238,6 +248,17 @@
        <div className="menu-style-controller">
          <Form {...formItemLayout}>
            {card ? <Collapse expandIconPosition="right" destroyInactivePanel={true} defaultActiveKey={options[0]} accordion={true}>
              {options.includes('height') ? <Panel header="高度" key="height">
                <Col span={24}>
                  <Form.Item
                    colon={false}
                    label={<Icon title="高度" type="column-height" />}
                    labelCol={{xs: { span: 24 }, sm: { span: 4 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 20 }} }
                  >
                    <StyleInput defaultValue={card.height || ''} options={['px']} onChange={this.changeHeight}/>
                  </Form.Item>
                </Col>
              </Panel> : null}
              {options.includes('font') ? <Panel header="字体" key="font">
                <Col span={12}>
                  <Form.Item colon={false} label={<Icon title="字体大小" type="font-size" />}>
@@ -264,7 +285,7 @@
                  </Form.Item>
                </Col>
                <Col span={12}>
                  <Form.Item colon={false} label={<Icon title="行间距" type="line-height" />}>
                  <Form.Item colon={false} label={<Icon title="行高" type="line-height" />}>
                    <InputNumber defaultValue={card.lineHeight} min={1} max={10} precision={1} onChange={this.changeLineHeight} />
                  </Form.Item>
                </Col>
@@ -348,10 +369,19 @@
                <Col span={24}>
                  <Form.Item
                    colon={false}
                    label={<Icon title="边框" type="border-outer" />}
                    label={<Icon title="边框宽度" type="border-outer" />}
                    labelCol={{xs: { span: 24 }, sm: { span: 4 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 20 }} }
                  >
                    <ColorSketch defaultValue={card.border ? card.border.replace(/^1px solid /ig, '').replace('0px', 'transparent') : 'transparent'} onChange={this.submitBorder} />
                    <StyleInput defaultValue={card.borderWidth || ''} options={['px']} onChange={this.changeBorderWidth}/>
                  </Form.Item>
                </Col>
                <Col span={24}>
                  <Form.Item
                    colon={false}
                    label={<Icon title="边框颜色" type="bg-colors" />}
                    labelCol={{xs: { span: 24 }, sm: { span: 4 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 20 }} }
                  >
                    <ColorSketch defaultValue={card.borderColor || 'transparent'} onChange={this.changeBorderColor} />
                  </Form.Item>
                </Col>
                <Col span={24}>
@@ -360,7 +390,7 @@
                    label={<Icon title="圆角" type="radius-setting" />}
                    labelCol={{xs: { span: 24 }, sm: { span: 4 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 20 }} }
                  >
                    <StyleInput defaultValue={card.borderRadius || ''} width={210} options={['px', '%']} onChange={this.changeBorderRadius}/>
                    <StyleInput defaultValue={card.borderRadius || ''} options={['px', '%']} onChange={this.changeBorderRadius}/>
                  </Form.Item>
                </Col>
              </Panel> : null}
@@ -370,7 +400,7 @@
                    colon={false}
                    label={<Icon title="上边距" type="arrow-up"/>}
                  >
                    <StyleInput defaultValue={card.marginTop} width={80} options={['px', 'vh', 'vw']} onChange={(val) => this.changeMarginOrPadding(val, 'marginTop')}/>
                    <StyleInput defaultValue={card.marginTop} options={['px', 'vh', 'vw']} onChange={(val) => this.changeMarginOrPadding(val, 'marginTop')}/>
                  </Form.Item>
                </Col>
                <Col span={12}>
@@ -378,7 +408,7 @@
                    colon={false}
                    label={<Icon title="下边距" type="arrow-down"/>}
                  >
                    <StyleInput defaultValue={card.marginBottom} width={80} options={['px', 'vh', 'vw']} onChange={(val) => this.changeMarginOrPadding(val, 'marginBottom')}/>
                    <StyleInput defaultValue={card.marginBottom} options={['px', 'vh', 'vw']} onChange={(val) => this.changeMarginOrPadding(val, 'marginBottom')}/>
                  </Form.Item>
                </Col>
                <Col span={12}>
@@ -386,7 +416,7 @@
                    colon={false}
                    label={<Icon title="左边距" type="arrow-left"/>}
                  >
                    <StyleInput defaultValue={card.marginLeft} width={80} options={['px', 'vh', 'vw']} onChange={(val) => this.changeMarginOrPadding(val, 'marginLeft')}/>
                    <StyleInput defaultValue={card.marginLeft} options={['px', 'vh', 'vw']} onChange={(val) => this.changeMarginOrPadding(val, 'marginLeft')}/>
                  </Form.Item>
                </Col>
                <Col span={12}>
@@ -394,7 +424,7 @@
                    colon={false}
                    label={<Icon title="右边距" type="arrow-right"/>}
                  >
                    <StyleInput defaultValue={card.marginRight} width={80} options={['px', 'vh', 'vw']} onChange={(val) => this.changeMarginOrPadding(val, 'marginRight')}/>
                    <StyleInput defaultValue={card.marginRight} options={['px', 'vh', 'vw']} onChange={(val) => this.changeMarginOrPadding(val, 'marginRight')}/>
                  </Form.Item>
                </Col>
              </Panel> : null}
@@ -404,7 +434,7 @@
                    colon={false}
                    label={<Icon title="上边距" type="arrow-up"/>}
                  >
                    <StyleInput defaultValue={card.paddingTop} width={80} options={['px', 'vh', 'vw']} onChange={(val) => this.changeMarginOrPadding(val, 'paddingTop')}/>
                    <StyleInput defaultValue={card.paddingTop} options={['px', 'vh', 'vw']} onChange={(val) => this.changeMarginOrPadding(val, 'paddingTop')}/>
                  </Form.Item>
                </Col>
                <Col span={12}>
@@ -412,7 +442,7 @@
                    colon={false}
                    label={<Icon title="下边距" type="arrow-down"/>}
                  >
                    <StyleInput defaultValue={card.paddingBottom} width={80} options={['px', 'vh', 'vw']} onChange={(val) => this.changeMarginOrPadding(val, 'paddingBottom')}/>
                    <StyleInput defaultValue={card.paddingBottom} options={['px', 'vh', 'vw']} onChange={(val) => this.changeMarginOrPadding(val, 'paddingBottom')}/>
                  </Form.Item>
                </Col>
                <Col span={12}>
@@ -420,7 +450,7 @@
                    colon={false}
                    label={<Icon title="左边距" type="arrow-left"/>}
                  >
                    <StyleInput defaultValue={card.paddingLeft} width={80} options={['px', 'vh', 'vw']} onChange={(val) => this.changeMarginOrPadding(val, 'paddingLeft')}/>
                    <StyleInput defaultValue={card.paddingLeft} options={['px', 'vh', 'vw']} onChange={(val) => this.changeMarginOrPadding(val, 'paddingLeft')}/>
                  </Form.Item>
                </Col>
                <Col span={12}>
@@ -428,7 +458,7 @@
                    colon={false}
                    label={<Icon title="右边距" type="arrow-right"/>}
                  >
                    <StyleInput defaultValue={card.paddingRight} width={80} options={['px', 'vh', 'vw']} onChange={(val) => this.changeMarginOrPadding(val, 'paddingRight')}/>
                    <StyleInput defaultValue={card.paddingRight} options={['px', 'vh', 'vw']} onChange={(val) => this.changeMarginOrPadding(val, 'paddingRight')}/>
                  </Form.Item>
                </Col>
              </Panel> : null}
src/menu/stylecontroller/styleInput/index.jsx
@@ -35,6 +35,10 @@
      _options = options
    }
    if (val === 'auto') {
      val = ''
    }
    let _val = parseInt(val)
    if (isNaN(_val)) {
@@ -106,7 +110,7 @@
            <Menu.Item key={option} style={{width: width}} onClick={() => this.submitValue(`${parseVal}${option}`)}>{parseVal} {option}</Menu.Item>
          ))}
        </Menu> : null
      } trigger="click">
      } trigger="hover">
        <div ref={dom => { this.input = dom }} style={{lineHeight: '32px'}}>
          <Input value={value} onChange={this.changeValue}/>
        </div>
src/mob/colorsketch/index.scss
@@ -7,13 +7,13 @@
    cursor: pointer;
    border-radius: 2px;
    box-shadow: 0 0 0 1px rgba(0, 0, 0, .1);
    width: calc(100% - 170px);
    width: calc(100% - 160px);
    height: 100%;
    border-radius: 2px;
  }
  .color-sketch-value {
    display: inline-block;
    width: 170px;
    width: 160px;
    padding-left: 10px;
    height: 25px;
    line-height: 25px;
src/mob/controller/index.jsx
@@ -258,7 +258,7 @@
  }
  render () {
    const { card, fontColor, backgroundColor, backgroundImage, bgimages, marginTop, marginTopVal, marginBottom, marginBottomVal } = this.state
    const { card, backgroundImage, bgimages, marginTop, marginTopVal, marginBottom, marginBottomVal } = this.state
    const formItemLayout = {
      labelCol: {
        xs: { span: 24 },
@@ -316,7 +316,6 @@
                  labelCol={{xs: { span: 24 }, sm: { span: 4 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 20 }} }
                >
                  <ColorSketch value={card.color || '#000000'} onChange={this.changeFontColor} />
                  <Input value={fontColor} onChange={this.changeFontColorInput} />
                </Form.Item>
              </Col>
              <Col span={24}>
@@ -368,7 +367,6 @@
                  labelCol={{xs: { span: 24 }, sm: { span: 4 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 20 }} }
                >
                  <ColorSketch value={card.backgroundColor || '#ffffff'} onChange={this.changeBackgroundColor} />
                  <Input value={backgroundColor} onChange={this.changeBackgroundColorInput} />
                </Form.Item>
              </Col>
              <Col span={24}>
src/mob/header/index.scss
@@ -56,11 +56,11 @@
  }
  >.ant-menu {
    float: left;
    width: unset;
    width: unset!important;
    .ant-menu-item {
      margin-bottom: 0;
      margin-bottom: 0!important;
      float: left;
      width: unset;
      width: unset!important;
      cursor: default;
      .anticon-arrow-left {
        height: 24px;
src/templates/formtabconfig/index.jsx
@@ -759,27 +759,7 @@
      newLText = Utils.formatOptions(DevUtils.getfunc(_param, btn, menu, _config))
      DelText = Utils.formatOptions(DevUtils.dropfunc(_param.funcName))
      this.refs.btnCreatFunc.exec(btn.innerFunc, newLText, DelText).then(result => {
        if (result !== 'success') return
        let isupdate = false
        _config.action = _config.action.map(item => {
          if (item.uuid === btn.uuid) {
            isupdate = true
            return btn
          } else {
            return item
          }
        })
        if (!isupdate) { // 操作不是修改,添加元素至列表
          _config.action.push(btn)
        }
        this.setState({
          config: _config
        })
      })
      this.refs.btnCreatFunc.exec(btn.innerFunc, newLText, DelText)
    })
  }
src/templates/sharecomponent/actioncomponent/index.jsx
@@ -686,39 +686,13 @@
   * @description 创建按钮存储过程
   */
  creatFunc = () => {
    const { config, menu } = this.props
    const { menu } = this.props
    let _config = fromJS(this.props.config).toJS()
    this.actionFormRef.handleConfirm().then(res => {
      let btn = res         // 按钮信息
      let newLText = ''     // 创建存储过程sql
      let DelText = ''      // 删除存储过程sql
      let _actionlist = fromJS(this.state.actionlist).toJS()
      _actionlist = _actionlist.filter(item => !item.origin || item.uuid === btn.uuid)
      let labelrepet = false
      _actionlist = _actionlist.map(item => {
        if (item.uuid !== btn.uuid && item.label === btn.label) {
          labelrepet = true
        }
        if (item.uuid === btn.uuid) {
          return btn
        } else {
          return item
        }
      })
      if (labelrepet) {
        notification.warning({
          top: 92,
          message: this.state.dict['model.name.exist'] + ' !',
          duration: 5
        })
        return
      }
      // 创建存储过程,必须填写内部函数名
      if (btn.intertype !== 'inner') {
@@ -816,35 +790,7 @@
      }).then(res => {
        if (!res) return
        this.refs.btnCreatFunc.exec(btn.innerFunc, newLText, DelText).then(result => {
          if (result !== 'success') return
          // 判断是否存在操作列
          let _hasGridbtn = _actionlist.filter(act => act.position === 'grid').length > 0
          let _gridBtn = config.gridBtn ? fromJS(config.gridBtn).toJS() : null
          if (_gridBtn) {
            _gridBtn.display = _hasGridbtn
          } else {
            _gridBtn = {
              display: _hasGridbtn,
              Align: 'center',
              IsSort: 'false',
              uuid: Utils.getuuid(),
              label: this.state.dict['model.form.column.action'],
              type: 'action',
              style: 'button',
              show: 'horizontal',
              Width: 120
            }
          }
          this.setState({
            actionlist: _actionlist
          }, () => {
            this.props.updateaction({...config, action: _actionlist, gridBtn: _gridBtn})
          })
        })
        this.refs.btnCreatFunc.exec(btn.innerFunc, newLText, DelText)
      })
    })
  }
src/templates/sharecomponent/actioncomponent/verifyexcelin/customscript/index.jsx
@@ -202,7 +202,10 @@
        fields = fields + ','
      }
      _value = `Insert into ${btn.sheet} (${fields}createuserid,createuser,createstaff,bid)\nSelect ${fields}@userid@,@username,@fullname,@BID@ From @${btn.sheet}`
      let database = btn.sheet.match(/(.*)\.(.*)\./ig) || ''
      let sheet = btn.sheet.replace(/(.*)\.(.*)\./ig, '')
      _value = `Insert into ${database}${sheet} (${fields}createuserid,createuser,createstaff,bid)\nSelect ${fields}@userid@,@username,@fullname,@BID@ From @${sheet}`
    } else {
      _value = value
    }
src/templates/zshare/createfunc/index.jsx
@@ -22,12 +22,10 @@
      loading: true
    })
    return new Promise(resolve => {
      this.createExec(resolve, innerFunc, newLText, DelText)
    })
    this.createExec(innerFunc, newLText, DelText)
  }
  
  createExec = (_resolve, innerFunc, newLText, DelText) => {
  createExec = (innerFunc, newLText, DelText) => {
    let isExist = false // 存储过程是否存在
    let cloudText = ''  // 云端存储结果
    let localfunc = ''  // 本地存储过程
@@ -175,6 +173,10 @@
      return Api.getLocalConfig(_param)
    }).then(res => {
      this.setState({
        loading: false
      })
      if (!res) return res
      
      // 处理新建结果
@@ -184,26 +186,13 @@
          message: res.message,
          duration: 5
        })
        return false
      } else {
        notification.success({
          top: 92,
          message: '创建成功',
          duration: 2
        })
        return true
      }
    }).then(res => {
      // 结果处理
      if (!res) {
        _resolve('error')
      } else {
        _resolve('success')
      }
      this.setState({
        loading: false
      })
    })
  }
src/utils/utils.js
@@ -161,9 +161,9 @@
      let reg = new RegExp('(^|\\s)' + item.key + '(\\s|$)', 'ig')
      value = value.replace(reg, item.value)
    })
    // 1、替换%符(数据库中解析后sql报错)
    // 替换%符(数据库中解析后sql报错)
    value = value.replace(/%/ig, ' mpercent ')
    // 1、encode编码(中文字符超出base64加密范围),2、base64加密
    // encode编码(中文字符超出base64加密范围)
    value = window.btoa(window.encodeURIComponent(value))
    // 插入字符
    let index = Math.floor(value.length / 2)
@@ -711,6 +711,9 @@
      fullName = sessionStorage.getItem('CloudFullName') || ''
    }
    let database = item.sheet.match(/(.*)\.(.*)\./ig) || ''
    let sheet = item.sheet.replace(/(.*)\.(.*)\./ig, '')
    let errors = []
    let _topline = btn.range || 0
    let upId = this.getuuid()
@@ -876,7 +879,7 @@
          _uniquesql += `
        /* 重复性验证 */
        Set @tbid=''
        Select top 1 @tbid=${_fields.join('+\' \'+')} from (select 1 as n,${unique.field} from @${item.sheet} ) a group by ${unique.field} having sum(n)>1
        Select top 1 @tbid=${_fields.join('+\' \'+')} from (select 1 as n,${unique.field} from @${sheet} ) a group by ${unique.field} having sum(n)>1
        
        If @tbid!=''
        Begin
@@ -885,7 +888,7 @@
        end
        
        Set @tbid=''
        Select top 1 @tbid=${_afields.join('+\' \'+')} from  @${item.sheet} a Inner join ${item.sheet} b on ${_fields_}
        Select top 1 @tbid=${_afields.join('+\' \'+')} from  @${sheet} a Inner join ${sheet} b on ${_fields_}
        
        If @tbid!=''
        Begin
@@ -916,20 +919,20 @@
      if (btn.default !== 'false') {
        _insert = `
        /* 默认sql */
        Insert into ${item.sheet} (${fields},createuserid,createuser,createstaff,bid)
        Select ${fields},@userid@,@username,@fullname,@BID@ From @${item.sheet}
        Insert into ${database}${sheet} (${fields},createuserid,createuser,createstaff,bid)
        Select ${fields},@userid@,@username,@fullname,@BID@ From @${sheet}
        `
      }
      _sql = `
        /* 系统生成 */
        declare @${item.sheet} table (${declarefields.join(',')},jskey nvarchar(50),BID nvarchar(50) )
        declare @${sheet} table (${declarefields.join(',')},jskey nvarchar(50),BID nvarchar(50) )
        Declare @UserName nvarchar(50),@FullName nvarchar(50),@ErrorCode nvarchar(50),@retmsg nvarchar(4000),@tbid Nvarchar(512)
        
        Select  @ErrorCode='', @retmsg='', @UserName='${userName}', @FullName='${fullName}'
        ${_initCustomScript}
        `
      _sqlInsert = `Insert into @${item.sheet} (${fields},jskey,BID)`
      _sqlInsert = `Insert into @${sheet} (${fields},jskey,BID)`
      _sqlBottom = `
        /* 默认sql */
        delete tmp_excel_in where upid=@upid@
@@ -939,7 +942,7 @@
        ${_prevCustomScript}
        ${_insert}
        ${_backCustomScript}
        Delete @${item.sheet}
        Delete @${sheet}
        
        aaa: select @ErrorCode as ErrorCode,@retmsg as retmsg`
@@ -958,7 +961,7 @@
    } else { // s_sDataDictb_excelIn 云端密钥验证参数
      _sql = `
        /* 系统生成 */
        declare @${item.sheet} table (jskey nvarchar(50))
        declare @${sheet} table (jskey nvarchar(50))
        Declare @UserName nvarchar(50),@FullName nvarchar(50),@ErrorCode nvarchar(50),@retmsg nvarchar(4000),@tbid Nvarchar(512)
        
        Select  @ErrorCode='', @retmsg='', @UserName='${userName}', @FullName='${fullName}'
src/views/menudesign/index.jsx
@@ -31,6 +31,7 @@
const TableComponent = asyncComponent(() => import('@/templates/sharecomponent/tablecomponent'))
sessionStorage.setItem('isEditState', 'true')
sessionStorage.setItem('delButtons', JSON.stringify([]))
class MenuDesign extends Component {
  state = {