king
2020-09-29 30273c297c59887434f44a75df75f13db6c8885c
2020-09-29
5个文件已修改
6个文件已添加
1119 ■■■■ 已修改文件
src/menu/actioncomponent/index.jsx 65 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/card/cardcellcomponent/index.jsx 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/card/cardcomponent/index.jsx 285 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/card/cardcomponent/index.scss 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/card/cardcomponent/settingform/index.jsx 404 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/card/cardcomponent/settingform/index.scss 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/card/data-card/index.jsx 88 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/stylecontroller/index.jsx 57 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/stylecontroller/styleInput/index.jsx 118 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/stylecontroller/styleInput/index.scss 44 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/mob/colorsketch/index.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/actioncomponent/index.jsx
@@ -464,32 +464,12 @@
          })
        }
      }).then(() => {
        // 判断是否存在操作列
        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,
          copying: false,
          visible: false
        }, () => {
          this.props.updateaction({...config, action: _actionlist, gridBtn: _gridBtn}, copyActionId)
          this.props.updateaction({...config, action: _actionlist}, copyActionId)
        })
      })
    })
@@ -686,25 +666,6 @@
        _actionlist = _actionlist.filter(item => item.uuid !== card.uuid)
        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
          }
        }
        let delcard = {
          type: 'action',
          card: card
@@ -713,7 +674,7 @@
        _this.setState({
          actionlist: _actionlist
        }, () => {
          _this.props.updateaction({...config, action: _actionlist, gridBtn: _gridBtn}, '', delcard)
          _this.props.updateaction({...config, action: _actionlist}, '', delcard)
        })
      },
      onCancel() {}
@@ -895,30 +856,10 @@
        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.props.updateaction({...config, action: _actionlist})
          })
        })
      })
src/menu/components/card/cardcellcomponent/index.jsx
@@ -17,7 +17,8 @@
class CardCellComponent extends Component {
  static propTpyes = {
    config: PropTypes.object,        // 菜单配置信息
    updateElement: PropTypes.func     // 菜单配置更新
    elements: PropTypes.array,       // 元素集
    updateElement: PropTypes.func    // 菜单配置更新
  }
  state = {
@@ -32,10 +33,10 @@
   * @description 搜索条件初始化
   */
  UNSAFE_componentWillMount () {
    const { config } = this.props
    const { elements } = this.props
    this.setState({
      elements: fromJS(config.elements).toJS()
      elements: fromJS(elements).toJS()
    })
  }
src/menu/components/card/cardcomponent/index.jsx
New file
@@ -0,0 +1,285 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import { is, fromJS } from 'immutable'
import { Modal, Popover, Icon, Switch } from 'antd'
import asyncComponent from '@/utils/asyncComponent'
import zhCN from '@/locales/zh-CN/model.js'
import enUS from '@/locales/en-US/model.js'
// import { getCardCellForm } from './formconfig'
import Utils from '@/utils/utils.js'
import MKEmitter from '@/utils/events.js'
import './index.scss'
const { confirm } = Modal
const CardCellComponent = asyncComponent(() => import('../cardcellcomponent'))
class CardBoxComponent extends Component {
  static propTpyes = {
    config: PropTypes.object,        // 菜单配置信息
    card: PropTypes.object,          // 卡片配置信息
    updateElement: PropTypes.func    // 菜单配置更新
  }
  state = {
    dict: localStorage.getItem('lang') !== 'en-US' ? zhCN : enUS,
    card: null,          // 卡片信息,包括正反面
    formlist: null,      // 设置表单信息
    elements: null,      // 编辑组
    visible: false,      // 模态框控制
    side: 'front'
  }
  /**
   * @description 搜索条件初始化
   */
  UNSAFE_componentWillMount () {
    const { card } = this.props
    this.setState({
      card: fromJS(card).toJS(),
      elements: fromJS(card.elements).toJS(),
    })
  }
  componentDidMount () {
    MKEmitter.addListener('cardAddElement', this.cardAddElement)
  }
  shouldComponentUpdate (nextProps, nextState) {
    return !is(fromJS(this.state), fromJS(nextState))
  }
  /**
   * @description 组件销毁,清除state更新,清除快捷键设置
   */
  componentWillUnmount () {
    this.setState = () => {
      return
    }
    MKEmitter.removeListener('cardAddElement', this.cardAddElement)
  }
  cardAddElement = (cardId, element) => {
    if (cardId !== this.props.config.uuid) return
    const { elements } = this.state
    this.setState({elements: [...elements, element]})
    this.handleElement(element)
  }
  /**
   * @description 按钮顺序调整
   */
  handleList = (list) => {
    const { config } = this.props
    this.setState({elements: list}, () => {
      this.props.updateElement({...config, elements: list})
    })
  }
  /**
   * @description 按钮编辑,获取按钮表单信息
   */
  handleElement = (card) => {
    this.setState({
      visible: true,
      card: card,
      // formlist: getCardCellForm(card)
    })
  }
  /**
   * @description 取消保存,如果元素为新添元素,则从序列中删除
   */
  editModalCancel = () => {
    const { card, elements } = this.state
    let _elements = null
    if (card.focus) {
      _elements = elements.filter(item => item.uuid !== card.uuid)
    } else {
      _elements = elements
    }
    this.setState({
      card: null,
      elements: _elements,
      visible: false
    })
  }
  /**
   * @description 搜索修改后提交保存
   * 1、去除系统默认搜索条件
   * 2、字段及提示文字重复校验
   * 3、更新下拉菜单可选集合
   * 4、下拉菜单数据源语法验证
   */
  handleSubmit = () => {
    const { config } = this.props
    const { elements } = this.state
    this.elementFormRef.handleConfirm().then(ele => {
      let _elements = elements.map(cell => {
        if (cell.uuid === ele.uuid) return ele
        return cell
      })
      this.setState({
        elements: _elements,
        visible: false
      }, () => {
        this.props.updateElement({...config, elements: _elements})
      })
    })
  }
  /**
   * @description 按钮删除
   */
  deleteElement = (card) => {
    const { config } = this.props
    const { dict, elements } = this.state
    let _this = this
    confirm({
      content: dict['model.confirm'] + dict['model.delete'] + '元素吗?',
      onOk() {
        let _elements = elements.filter(item => item.uuid !== card.uuid)
        _this.setState({
          elements: _elements
        }, () => {
          _this.props.updateElement({...config, elements: _elements})
        })
      },
      onCancel() {}
    })
  }
  changeSide = () => {
    const { card } = this.props
    const { side } = this.state
    let _side = ''
    let _elements = null
    if (side === 'front') {
      _side = 'back'
    } else {
      _side = 'front'
    }
    if (_side === 'front') {
      _elements = fromJS(card.elements).toJS()
    } else {
      _elements = fromJS(card.backElements).toJS()
    }
    this.setState({side: _side, elements: _elements})
  }
  addElement = () => {
    const { card } = this.state
    let newcard = {}
    newcard.uuid = Utils.getuuid()
    newcard.focus = true
    newcard.eleType = 'text'
    newcard.datatype = 'dynamic'
    newcard.color = 'rgba(0,0,0,0.85)'
    newcard.padding = '5px'
    newcard.align = 'left'
    // 注册事件-添加元素
    MKEmitter.emit('cardAddElement', card.uuid, newcard)
  }
  addButton = () => {
    const { card } = this.state
    let newcard = {}
    newcard.uuid = Utils.getuuid()
    newcard.focus = true
    newcard.label = 'button'
    newcard.sqlType = ''
    newcard.Ot = 'requiredSgl'
    newcard.OpenType = 'prompt'
    newcard.icon = ''
    newcard.class = 'default'
    newcard.intertype = 'system'
    newcard.method = 'POST'
    newcard.execSuccess = 'grid'
    newcard.execError = 'never'
    newcard.popClose = 'never'
    newcard.errorTime = 10
    newcard.verify = null
    newcard.show = 'link'
    // 注册事件-添加元素
    MKEmitter.emit('addButton', card.uuid, newcard)
  }
  changeStyle = () => {
    const { card } = this.state
    MKEmitter.emit('changeStyle', [card.uuid], ['font', 'background', 'border'], {})
  }
  render() {
    // const { config } = this.props
    const { card, elements } = this.state
    return (
      <div className={'ant-col card-item ant-col-' + (card.setting.width || 6)} style={{height: card.setting.height ? card.setting.height + 'px' : 'auto'}}>
        <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="style" title="调整样式" onClick={this.changeStyle} type="font-colors" />
              <Switch size="small" onClick={this.changeSide} defaultChecked />
            </div>
          } trigger="hover">
            <Icon type="tool" />
          </Popover>
        </div>
      </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>
    )
  }
}
export default CardBoxComponent
src/menu/components/card/cardcomponent/index.scss
New file
@@ -0,0 +1,25 @@
.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
New file
@@ -0,0 +1,404 @@
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 { 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 {
  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
  }
  handleConfirm = () => {
    // 表单提交时检查输入值是否正确
    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)
        }
      })
    })
  }
  render() {
    const formItemLayout = {
      labelCol: {
        xs: { span: 24 },
        sm: { span: 7 }
      },
      wrapperCol: {
        xs: { span: 24 },
        sm: { span: 17 }
      }
    }
    return (
      <Form {...formItemLayout} className="menu-card-detail-form" id="card-winter">
        <Row gutter={24}>{this.getFields()}</Row>
      </Form>
    )
  }
}
export default Form.create()(MainSearch)
src/menu/components/card/cardcomponent/settingform/index.scss
New file
@@ -0,0 +1,24 @@
.menu-card-detail-form {
  min-height: 190px;
  .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, Switch } from 'antd'
import { Icon, Popover } from 'antd'
import asyncComponent from '@/utils/asyncComponent'
import asyncIconComponent from '@/utils/asyncIconComponent'
@@ -15,8 +15,7 @@
const SettingComponent = asyncIconComponent(() => import('@/menu/datasource'))
const WrapComponent = asyncIconComponent(() => import('./wrapsetting'))
// const ActionComponent = asyncComponent(() => import('@/menu/actioncomponent'))
const CardCellComponent = asyncComponent(() => import('../cardcellcomponent'))
const CardComponent = asyncComponent(() => import('../cardcomponent'))
class antvBarLineChart extends Component {
  static propTpyes = {
@@ -60,12 +59,17 @@
        name: card.name,
        subtype: card.subtype,
        setting: { interType: 'system' },
        wrap: { name: card.name, width: 24, cardWidth: 6, addable: 'false', switch: 'false' },
        wrap: { name: card.name, width: 24, addable: 'false', switch: 'false' },
        style: { marginLeft: '8px', marginRight: '8px', marginTop: '8px', marginBottom: '8px' },
        columns: [],
        scripts: [],
        // action: [],
        elements: []
        subcards: [{
          uuid: Utils.getuuid(),
          setting: { width: 6 },
          elements: [],
          backElements: []
        }]
      }
      this.setState({
        card: _card
@@ -107,56 +111,7 @@
    this.props.updateConfig(component)
  }
  addElement = () => {
    const { card } = this.state
    let newcard = {}
    newcard.uuid = Utils.getuuid()
    newcard.focus = true
    newcard.eleType = 'text'
    newcard.datatype = 'dynamic'
    newcard.color = 'rgba(0,0,0,0.85)'
    newcard.padding = '5px'
    newcard.align = 'left'
    // 注册事件-添加元素
    MKEmitter.emit('cardAddElement', card.uuid, newcard)
  }
  addButton = () => {
    const { card } = this.state
    let newcard = {}
    newcard.uuid = Utils.getuuid()
    newcard.focus = true
    newcard.label = 'button'
    newcard.sqlType = ''
    newcard.Ot = 'requiredSgl'
    newcard.OpenType = 'prompt'
    newcard.icon = ''
    newcard.class = 'default'
    newcard.intertype = 'system'
    newcard.method = 'POST'
    newcard.execSuccess = 'grid'
    newcard.execError = 'never'
    newcard.popClose = 'never'
    newcard.errorTime = 10
    newcard.verify = null
    newcard.show = 'link'
    // 注册事件-添加元素
    MKEmitter.emit('addButton', card.uuid, newcard)
  }
  changeStyle = () => {
    const { card } = this.state
    MKEmitter.emit('changeStyle', [card.uuid], ['font', 'background', 'border'], {})
  }
  changeOutStyle = () => {
    const { card } = this.state
    MKEmitter.emit('changeStyle', [card.uuid], ['background', 'border', 'padding', 'margin'], card.style)
@@ -165,16 +120,12 @@
  getStyle = (comIds, style) => {
    const { card } = this.state
    if (comIds[0] !== card.uuid) return
    if (comIds.length > 1 || comIds[0] !== card.uuid) return
    this.setState({
      card: {...card, style}
    })
    console.log(style)
  }
  changeSide = () => {
    this.setState(prev => ({ back: !prev.back }))
  }
  render() {
@@ -185,29 +136,14 @@
        <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={
          <div className="mk-popover-control">
            <WrapComponent config={card} updateConfig={this.updateComponent} />
            <Icon className="style" title="调整样式" onClick={this.changeOutStyle} type="font-colors" />
            <Icon className="style" title="调整样式" onClick={this.changeStyle} type="font-colors" />
            <Icon className="close" title="delete" type="delete" onClick={() => this.props.deletecomponent(card.uuid)} />
            <SettingComponent config={card} updateConfig={this.updateComponent} />
          </div>
        } trigger="hover">
          <Icon type="tool" />
        </Popover>
        <div className={'ant-col card-item ant-col-' + (card.wrap.cardWidth || 6)} style={{height: card.wrap.height ? card.wrap.height + 'px' : 'auto'}}>
          <CardCellComponent config={card} updateElement={this.updateComponent}/>
          {/* <ActionComponent plus="false" config={card} updateaction={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="style" title="调整样式" onClick={this.changeStyle} type="font-colors" />
                <Switch size="small" onClick={this.changeSide} defaultChecked />
              </div>
            } trigger="hover">
              <Icon type="tool" />
            </Popover>
          </div>
        </div>
        {card.subcards.map(subcard => (<CardComponent key={subcard.uuid} config={card} card={subcard} updateElement={this.updateComponent}/>))}
        {card.wrap.addable === 'true' ? <div className="card-add-button"><Icon type="plus" /></div> : null}
      </div>
    )
src/menu/stylecontroller/index.jsx
@@ -7,6 +7,7 @@
import zhCN from '@/locales/zh-CN/mob.js'
import enUS from '@/locales/en-US/mob.js'
import ColorSketch from '@/mob/colorsketch'
import StyleInput from './styleInput'
import FileUpload from '@/tabviews/zshare/fileupload'
import './index.scss'
@@ -23,7 +24,6 @@
    dict: localStorage.getItem('lang') !== 'en-US' ? zhCN : enUS,
    card: null,
    comIds: [],
    fontColor: '#000000',
    bgimages: [],
    backgroundImage: '',
    options: [],
@@ -135,19 +135,7 @@
   * @description 修改字体颜色 ,颜色控件
   */
  changeFontColor = (val) => {
    this.setState({
      fontColor: val
    })
    this.updateStyle({color: val})
  }
  /**
   * @description 修改字体颜色 ,手动输入
   */
  changeFontColorInput = (e) => {
    this.setState({
      fontColor: e.target.value
    })
  }
  /**
@@ -211,19 +199,12 @@
    this.updateStyle({border: border})
  }
  changeBorderRadius = (e) => {
    let val = e.target.value
  changeBorderRadius = (val) => {
    this.updateStyle({borderRadius: val})
  }
  changeMarginOrPadding = (val, type) => {
    val = parseInt(val)
    if (isNaN(val)) {
      val = 0
    }
    this.updateStyle({[type]: `${val}px`})
    this.updateStyle({[type]: val})
  }
  render () {
@@ -243,7 +224,7 @@
      <Drawer
        title={
          <div className="header-logo">
            <img src="http://cloud.mk9h.cn/Content/images/upload/2020-03-26/2020032615132185788026_xiazai.png" alt=""/>
            <img src={window.GLOB.mainlogo} alt=""/>
          </div>
        }
        placement="left"
@@ -284,12 +265,12 @@
                </Col>
                <Col span={12}>
                  <Form.Item colon={false} label={<Icon title="行间距" type="line-height" />}>
                    <InputNumber defaultValue={card.lineHeight || 1.5} min={1} max={10} precision={1} onChange={this.changeLineHeight} />
                    <InputNumber defaultValue={card.lineHeight} min={1} max={10} precision={1} onChange={this.changeLineHeight} />
                  </Form.Item>
                </Col>
                <Col span={12}>
                  <Form.Item colon={false} label={<Icon title="字间距" type="column-width" />}>
                    <InputNumber defaultValue={card.letterSpacing || 0} min={0} max={100} precision={0} onChange={this.changeLetterSpacing}/>
                    <InputNumber defaultValue={card.letterSpacing} min={0} max={100} precision={0} onChange={this.changeLetterSpacing}/>
                  </Form.Item>
                </Col>
                <Col span={24}>
@@ -298,7 +279,7 @@
                    label={<Icon title="字体颜色" type="font-colors" />}
                    labelCol={{xs: { span: 24 }, sm: { span: 4 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 20 }} }
                  >
                    <ColorSketch value={card.color || '#000000'} onChange={this.changeFontColor} />
                    <ColorSketch value={card.color || 'rgba(0, 0, 0, 0.85)'} onChange={this.changeFontColor} />
                  </Form.Item>
                </Col>
                <Col span={24}>
@@ -379,13 +360,7 @@
                    label={<Icon title="圆角" type="radius-setting" />}
                    labelCol={{xs: { span: 24 }, sm: { span: 4 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 20 }} }
                  >
                    <Radio.Group onChange={this.changeBorderRadius} defaultValue={card.borderRadius || ''}>
                      <Radio value="0px">无</Radio>
                      <Radio value="2px">2px</Radio>
                      <Radio value="4px">4px</Radio>
                      <Radio value="25%">25%</Radio>
                      <Radio value="50%">50%</Radio>
                    </Radio.Group>
                    <StyleInput defaultValue={card.borderRadius || ''} width={210} options={['px', '%']} onChange={this.changeBorderRadius}/>
                  </Form.Item>
                </Col>
              </Panel> : null}
@@ -395,7 +370,7 @@
                    colon={false}
                    label={<Icon title="上边距" type="arrow-up"/>}
                  >
                    <InputNumber defaultValue={card.marginTop || 0} min={0} max={1000} precision={0} onChange={(val) => this.changeMarginOrPadding(val, 'marginTop')}/>
                    <StyleInput defaultValue={card.marginTop} width={80} options={['px', 'vh', 'vw']} onChange={(val) => this.changeMarginOrPadding(val, 'marginTop')}/>
                  </Form.Item>
                </Col>
                <Col span={12}>
@@ -403,7 +378,7 @@
                    colon={false}
                    label={<Icon title="下边距" type="arrow-down"/>}
                  >
                    <InputNumber defaultValue={card.marginBottom || 0} min={0} max={1000} precision={0} onChange={(val) => this.changeMarginOrPadding(val, 'marginBottom')}/>
                    <StyleInput defaultValue={card.marginBottom} width={80} options={['px', 'vh', 'vw']} onChange={(val) => this.changeMarginOrPadding(val, 'marginBottom')}/>
                  </Form.Item>
                </Col>
                <Col span={12}>
@@ -411,7 +386,7 @@
                    colon={false}
                    label={<Icon title="左边距" type="arrow-left"/>}
                  >
                    <InputNumber defaultValue={card.marginLeft || 0} min={0} max={1000} precision={0} onChange={(val) => this.changeMarginOrPadding(val, 'marginLeft')}/>
                    <StyleInput defaultValue={card.marginLeft} width={80} options={['px', 'vh', 'vw']} onChange={(val) => this.changeMarginOrPadding(val, 'marginLeft')}/>
                  </Form.Item>
                </Col>
                <Col span={12}>
@@ -419,7 +394,7 @@
                    colon={false}
                    label={<Icon title="右边距" type="arrow-right"/>}
                  >
                    <InputNumber defaultValue={card.marginRight || 0} min={0} max={1000} precision={0} onChange={(val) => this.changeMarginOrPadding(val, 'marginRight')}/>
                    <StyleInput defaultValue={card.marginRight} width={80} options={['px', 'vh', 'vw']} onChange={(val) => this.changeMarginOrPadding(val, 'marginRight')}/>
                  </Form.Item>
                </Col>
              </Panel> : null}
@@ -429,7 +404,7 @@
                    colon={false}
                    label={<Icon title="上边距" type="arrow-up"/>}
                  >
                    <InputNumber defaultValue={card.paddingTop || 0} min={0} max={1000} precision={0} onChange={(val) => this.changeMarginOrPadding(val, 'paddingTop')}/>
                    <StyleInput defaultValue={card.paddingTop} width={80} options={['px', 'vh', 'vw']} onChange={(val) => this.changeMarginOrPadding(val, 'paddingTop')}/>
                  </Form.Item>
                </Col>
                <Col span={12}>
@@ -437,7 +412,7 @@
                    colon={false}
                    label={<Icon title="下边距" type="arrow-down"/>}
                  >
                    <InputNumber defaultValue={card.paddingBottom || 0} min={0} max={1000} precision={0} onChange={(val) => this.changeMarginOrPadding(val, 'paddingBottom')}/>
                    <StyleInput defaultValue={card.paddingBottom} width={80} options={['px', 'vh', 'vw']} onChange={(val) => this.changeMarginOrPadding(val, 'paddingBottom')}/>
                  </Form.Item>
                </Col>
                <Col span={12}>
@@ -445,7 +420,7 @@
                    colon={false}
                    label={<Icon title="左边距" type="arrow-left"/>}
                  >
                    <InputNumber defaultValue={card.paddingLeft || 0} min={0} max={1000} precision={0} onChange={(val) => this.changeMarginOrPadding(val, 'paddingLeft')}/>
                    <StyleInput defaultValue={card.paddingLeft} width={80} options={['px', 'vh', 'vw']} onChange={(val) => this.changeMarginOrPadding(val, 'paddingLeft')}/>
                  </Form.Item>
                </Col>
                <Col span={12}>
@@ -453,7 +428,7 @@
                    colon={false}
                    label={<Icon title="右边距" type="arrow-right"/>}
                  >
                    <InputNumber defaultValue={card.paddingRight || 0} min={0} max={1000} precision={0} onChange={(val) => this.changeMarginOrPadding(val, 'paddingRight')}/>
                    <StyleInput defaultValue={card.paddingRight} width={80} options={['px', 'vh', 'vw']} onChange={(val) => this.changeMarginOrPadding(val, 'paddingRight')}/>
                  </Form.Item>
                </Col>
              </Panel> : null}
src/menu/stylecontroller/styleInput/index.jsx
New file
@@ -0,0 +1,118 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import { is, fromJS } from 'immutable'
import { Menu, Popover, Input } from 'antd'
import './index.scss'
class StyleInput extends Component {
  static propTpyes = {
    defaultValue: PropTypes.any,
    options: PropTypes.any,
    value: PropTypes.any,
    onChange: PropTypes.func,
  }
  state = {
    value: '',
    parseVal: '',
    width: '',
    options: null
  }
  UNSAFE_componentWillMount () {
    const { defaultValue, value, options } = this.props
    let val = ''
    let _options = ['px']
    if (value !== undefined) {
      val = value
    } else if (defaultValue !== undefined) {
      val = defaultValue
    }
    if (options && options.length > 0) {
      _options = options
    }
    let _val = parseInt(val)
    if (isNaN(_val)) {
      _val = ''
    }
    this.setState({value: val, options: _options, parseVal: _val})
  }
  shouldComponentUpdate (nextProps, nextState) {
    return !is(fromJS(this.state), fromJS(nextState))
  }
  UNSAFE_componentWillReceiveProps(nextProps) {
    if (nextProps.value !== undefined && nextProps.value !== this.state.value) {
      this.setState({ value: nextProps.value })
    }
  }
  componentDidMount () {
    this.setState({width: (this.input.offsetWidth - 10) + 'px'})
  }
  /**
   * @description 组件销毁,清除state更新,清除快捷键设置
   */
  componentWillUnmount () {
    this.setState = () => {
      return
    }
  }
  changeValue = (e) => {
    let val = e.target.value
    let _val = parseInt(val)
    if (isNaN(_val)) {
      _val = ''
    }
    this.setState({
      value: val,
      parseVal: _val
    })
    if (!val && this.props.onChange) {
      this.props.onChange('0px')
    }
  }
  submitValue = (val) => {
    this.setState({
      value: val
    })
    if (this.props.onChange) {
      this.props.onChange(val)
    }
  }
  render () {
    const { value, options, parseVal, width } = this.state
    return (
      <Popover placement="bottom" overlayClassName="style-input-popover" content={
        parseVal !== '' ?
        <Menu>
          {options.map(option => (
            <Menu.Item key={option} style={{width: width}} onClick={() => this.submitValue(`${parseVal}${option}`)}>{parseVal} {option}</Menu.Item>
          ))}
        </Menu> : null
      } trigger="click">
        <div ref={dom => { this.input = dom }} style={{lineHeight: '32px'}}>
          <Input value={value} onChange={this.changeValue}/>
        </div>
      </Popover>
    )
  }
}
export default StyleInput
src/menu/stylecontroller/styleInput/index.scss
New file
@@ -0,0 +1,44 @@
.style-input-popover {
  padding-top: 0px;
  z-index: 1090!important;
  .ant-popover-inner-content {
    padding: 0px 5px;
    .ant-menu-root.ant-menu-vertical {
      border: 0;
      .ant-menu-item {
        height: 30px;
        cursor: pointer;
        line-height: 30px;
      }
      .ant-menu-item:not(:last-child) {
        margin-bottom: 0px;
      }
      .ant-menu-item:first-child {
        margin-top: 10px;
      }
      .ant-menu-item:last-child {
        margin-bottom: 10px;
      }
    }
  }
  .ant-popover-arrow {
    display: none;
  }
  .ant-popover-content::before {
    content: ' ';
    position: absolute;
    width: 100%;
    height: 5px;
    top: -5px;
  }
  .ant-popover-content::after {
    content: ' ';
    position: absolute;
    width: 100%;
    height: 5px;
    bottom: -5px;
  }
}
.style-input-popover.ant-popover-placement-top {
  padding-bottom: 0px;
}
src/mob/colorsketch/index.jsx
@@ -31,7 +31,7 @@
  }
  UNSAFE_componentWillReceiveProps(nextProps) {
    if (nextProps.value && nextProps.value !== this.state.color) {
    if (nextProps.value !== undefined && nextProps.value !== this.state.color) {
      this.setState({ color: nextProps.value })
    }
  }