king
2020-09-24 6ed64ed071c75901ed8848131bfefa51c5c27fce
2020-09-24
16个文件已修改
8个文件已添加
1186 ■■■■■ 已修改文件
src/components/sidemenu/config.jsx 16 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/actioncomponent/actionform/index.jsx 44 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/actioncomponent/dragaction/card.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/actioncomponent/dragaction/index.jsx 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/actioncomponent/formconfig.jsx 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/actioncomponent/index.jsx 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/bgcontroller/index.jsx 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/card/cardcellcomponent/dragaction/card.jsx 67 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/card/cardcellcomponent/dragaction/index.jsx 89 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/card/cardcellcomponent/dragaction/index.scss 32 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/card/cardcellcomponent/elementform/index.jsx 336 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/card/cardcellcomponent/elementform/index.scss 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/card/cardcellcomponent/formconfig.jsx 238 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/card/cardcellcomponent/index.jsx 188 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/card/cardcellcomponent/index.scss 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/card/data-card/index.jsx 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/card/data-card/index.scss 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/datasource/verifycard/utils.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/mob/colorsketch/index.jsx 13 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/mob/colorsketch/index.scss 27 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/mob/controller/index.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/actioncomponent/index.jsx 17 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/zshare/createinterface/index.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/option.js 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/sidemenu/config.jsx
@@ -177,14 +177,14 @@
      MenuNo: 'bd_msn_sms_tempM',
      MenuName: '大于短信模板',
      text: '大于短信模板'
    }, {
      src: '',
      PageParam: {OpenType: 'newtab', Template: 'ManageTable'},
      type: 'ManageTable',
      MenuID: '1599613340050c8nu6rbst9d4emnnbsq',
      MenuNo: 's_sms_qxM',
      MenuName: '奇云短信模板',
      text: '奇云短信模板'
    // }, {
    //   src: '',
    //   PageParam: {OpenType: 'newtab', Template: 'ManageTable'},
    //   type: 'ManageTable',
    //   MenuID: '1599613340050c8nu6rbst9d4emnnbsq',
    //   MenuNo: 's_sms_qxM',
    //   MenuName: '奇云短信模板',
    //   text: '奇云短信模板'
    }]
  }, {
    MenuID: 'systemPayManage',
src/menu/actioncomponent/actionform/index.jsx
@@ -6,7 +6,6 @@
import Api from '@/api'
import options from '@/store/options.js'
import Utils from '@/utils/utils.js'
import './index.scss'
const { TextArea } = Input
@@ -16,7 +15,7 @@
  exec: ['label', 'OpenType', 'intertype', 'Ot', 'show', 'icon', 'class', 'execSuccess', 'execError'],
  excelIn: ['label', 'Ot', 'OpenType', 'intertype', 'show', 'icon', 'class', 'sheet', 'execSuccess', 'execError'],
  excelOut: ['label', 'OpenType', 'intertype', 'show', 'icon', 'class', 'execSuccess', 'execError', 'pagination', 'search'],
  popview: ['label', 'Ot', 'OpenType', 'show', 'icon', 'class', 'tabType', 'linkTab', 'popClose'],
  popview: ['label', 'Ot', 'OpenType', 'show', 'icon', 'class', 'popClose'],
  tab: ['label', 'Ot', 'OpenType', 'show', 'icon', 'class', 'linkmenu'],
  innerpage: ['label', 'Ot', 'OpenType', 'pageTemplate', 'show', 'icon', 'class'],
  funcbutton: ['label', 'OpenType', 'funcType', 'show', 'icon', 'class']
@@ -28,7 +27,6 @@
    setting: PropTypes.object,   // 页面设置
    formlist: PropTypes.any,     // 表单信息
    card: PropTypes.any,         // 按钮信息
    tabs: PropTypes.array,       // 所有标签页
    inputSubmit: PropTypes.any   // 回车提交事件
  }
@@ -119,14 +117,6 @@
          } else {
            item.options = this.state.insertUpdateOptions
          }
        } else if (item.key === 'linkTab') {
          item.options = [
            {
              value: '',
              text: '新建'
            },
            ...this.props.tabs
          ]
        } else if (item.key === 'OpenType') {
          item.initVal = _opentype
        }
@@ -245,26 +235,6 @@
          _fieldval.class = 'dgreen'
        }
        this.props.form.setFieldsValue(_fieldval)
      })
    } else if (key === 'tabType') {
      let _tabs = this.props.tabs.filter(tab => tab.type === value)
      let _fieldval = {}
      this.setState({
        formlist: this.state.formlist.map(item => {
          if (item.key === 'linkTab') {
            item.options = [
              {
                value: '',
                text: '新建'
              },
              ..._tabs
            ]
          }
          return item
        })
      }, () => {
        this.props.form.setFieldsValue(_fieldval)
      })
    } else if (key === 'funcType') {
@@ -643,8 +613,13 @@
          values.uuid = this.props.card.uuid
          values.verify = this.props.card.verify || null
          if (values.show === 'icon') {
          if (values.show === 'icon' && !values.icon) {
            notification.warning({
              top: 92,
              message: '请选择图标!',
              duration: 5
            })
            return
          } else if (values.OpenType === 'excelOut') {
            if (values.intertype === 'system' && setting.interType !== 'system') {
              notification.warning({
@@ -656,8 +631,7 @@
            }
            
            values.Ot = 'notRequired'
          } else if (values.OpenType === 'popview' && !values.linkTab) { // 没有关联标签(新建时),创建新标签Id
            values.linkTab = Utils.getuuid()
          } else if (values.OpenType === 'popview') {
            values.createTab = true // 用于标记按钮复制时,是否复制原有标签
          } else if (values.OpenType === 'funcbutton') { // 转换打印时打开方式
            if (values.funcType === 'print') {
src/menu/actioncomponent/dragaction/card.jsx
@@ -38,7 +38,7 @@
  let btnElement = null
  if (card.show === 'icon') {
    btnElement = (<Icon type={card.icon} className={'mk-icon mk-' + card.class}/>)
    btnElement = (card.icon ? <Icon type={card.icon} className={'mk-icon mk-' + card.class}/> : null)
  } else if (card.show === 'link') {
    btnElement = (<span className={'mk-link mk-' + card.class}>{card.label}{card.icon ? <Icon type={card.icon}/> : null}</span>)
  } else {
src/menu/actioncomponent/dragaction/index.jsx
@@ -150,8 +150,7 @@
          doubleClickCard={doubleClickBtn}
        />
      ))}
      <Icon type="plus" onClick={addaction}/>
      <Icon type="plus" title="添加按钮" onClick={addaction}/>
    </div>
  )
}
src/menu/actioncomponent/formconfig.jsx
@@ -161,14 +161,6 @@
    },
    {
      type: 'select',
      key: 'linkTab',
      label: '关联标签',
      initVal: card.linkTab || '',
      required: false,
      options: []
    },
    {
      type: 'select',
      key: 'pageTemplate',
      label: Formdict['model.form.newpage.type'],
      initVal: card.pageTemplate || '',
src/menu/actioncomponent/index.jsx
@@ -28,7 +28,6 @@
  static propTpyes = {
    type: PropTypes.string,          // 菜单类型,主表或子表
    config: PropTypes.object,        // 菜单配置信息
    tabs: PropTypes.array,           // 所有标签
    setSubConfig: PropTypes.func,    // 设置子配置信息
    updateaction: PropTypes.func     // 菜单配置更新
  }
@@ -921,7 +920,6 @@
          <ActionForm
            dict={dict}
            card={card}
            tabs={this.props.tabs}
            formlist={this.state.formlist}
            inputSubmit={this.handleSubmit}
            setting={config.setting}
src/menu/bgcontroller/index.jsx
@@ -60,22 +60,6 @@
  }
  /**
   * @description 修改字体颜色 ,手动输入
   */
  changeBackgroundColorInput = (e) => {
    let val = e.target.value
    this.setState({
      backgroundColor: val
    })
    let config = fromJS(this.props.config).toJS()
    config.style.backgroundColor = val
    this.props.updateConfig(config)
    // if (/^#([0-9a-fA-F]{6}|[0-9a-fA-F]{3})$|^[rR][gG][Bb][Aa]?[(]([\s]*(2[0-4][0-9]|25[0-5]|[01]?[0-9][0-9]?),){2}[\s]*(2[0-4][0-9]|25[0-5]|[01]?[0-9][0-9]?),?[\s]*(0\.\d{1,2}|1|0)?[)]{1}$/.test(val)) {}
  }
  /**
   * @description 手动修改路径
   */
  changeImage = (e) => {
@@ -129,8 +113,7 @@
      <div className="menu-background-controller">
        <Form {...formItemLayout}>
          <Form.Item className="color-control" colon={false} label="颜色">
            <ColorSketch color={backgroundColor} changeColor={this.changeBackgroundColor} />
            <Input value={backgroundColor} onChange={this.changeBackgroundColorInput} />
            <ColorSketch value={backgroundColor} onChange={this.changeBackgroundColor} />
          </Form.Item>
          <Form.Item colon={false} label="图片">
            <FileUpload value={bgimages} maxFile={2} fileType="text" onChange={this.imgChange}/>
src/menu/components/card/cardcellcomponent/dragaction/card.jsx
New file
@@ -0,0 +1,67 @@
import React from 'react'
import { useDrag, useDrop } from 'react-dnd'
import { Icon, Popover, Slider } from 'antd'
import './index.scss'
const Card = ({ id, cardIds, card, moveCard, findCard, editCard, delCard }) => {
  const originalIndex = findCard(id).index
  const [{ isDragging }, drag] = useDrag({
    item: { type: 'action', id, originalIndex },
    collect: monitor => ({
      isDragging: monitor.isDragging(),
    }),
  })
  const [, drop] = useDrop({
    accept: 'action',
    canDrop: () => true,
    drop({ id: draggedId }) {
      if (!draggedId) return
      if (!cardIds.includes(draggedId)) return
      if (draggedId !== id) {
        const { index: overIndex } = findCard(id)
        moveCard(draggedId, overIndex)
      }
    },
  })
  let _style = {opacity: isDragging ? 0 : 1}
  _style.textAlign = card.align
  _style.color = card.color
  if (card.padding) {
    _style.padding = card.padding
  }
  const getContent = () => {
    if (card.eleType === 'text' || card.eleType === 'number') {
      return card.value
    } else if (card.eleType === 'icon') {
      return (<Icon type={card.icon}/>)
    } else if (card.eleType === 'slider') {
      return (
        <div className="ant-slider">
          <div className="ant-slider-rail"></div>
          <div className="ant-slider-track" style={{width: '30%', backgroundColor: card.color}}></div>
          <div className="ant-slider-handle" style={{left: '30%', borderColor: card.color}}></div>
          <div style={{display: 'none'}}><Slider value={30} tooltipVisible={false} /></div>
        </div>
      )
    }
  }
  return (
    <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={
      <div className="mk-popover-control">
        <Icon className="edit" title="edit" type="edit" onClick={() => editCard(id)} />
        <Icon className="close" title="close" type="close" onClick={() => delCard(id)} />
      </div>
    } trigger="hover">
      <div ref={node => drag(drop(node))} className={'ant-col card-cell ant-col-' + card.width} style={_style}>
        {getContent()}
      </div>
    </Popover>
  )
}
export default Card
src/menu/components/card/cardcellcomponent/dragaction/index.jsx
New file
@@ -0,0 +1,89 @@
import React, { useState } from 'react'
import { useDrop } from 'react-dnd'
import { is, fromJS } from 'immutable'
import update from 'immutability-helper'
import { Icon } from 'antd'
import Utils from '@/utils/utils.js'
import Card from './card'
import './index.scss'
const Container = ({type, list, handleList, handleMenu, deleteMenu }) => {
  const [cards, setCards] = useState(list)
  const moveCard = (id, atIndex) => {
    const { card, index } = findCard(id)
    const _cards = update(cards, { $splice: [[index, 1], [atIndex, 0, card]] })
    handleList(_cards)
  }
  if (!is(fromJS(cards), fromJS(list))) {
    setCards(list)
  }
  const findCard = id => {
    const card = cards.filter(c => `${c.uuid}` === id)[0]
    return {
      card,
      index: cards.indexOf(card),
    }
  }
  const editCard = id => {
    const { card } = findCard(id)
    handleMenu(card)
  }
  const delCard = id => {
    const { card } = findCard(id)
    deleteMenu(card)
  }
  let cardIds = cards.map(card => card.uuid)
  const [, drop] = useDrop({
    accept: 'action',
    drop() {}
  })
  const addelement = () => {
    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'
    let targetId = cards.length > 0 ? cards[cards.length - 1].uuid : 0
    const { index: overIndex } = findCard(`${targetId}`)
    let targetIndex = overIndex
    targetIndex++
    const _cards = update(cards, { $splice: [[targetIndex, 0, newcard]] })
    handleList(_cards, newcard)
  }
  return (
    <div ref={drop} className="ant-row card-detail-row">
      {cards.map(card => (
        <Card
          id={card.uuid}
          key={card.uuid}
          cardIds={cardIds}
          card={card}
          moveCard={moveCard}
          editCard={editCard}
          delCard={delCard}
          findCard={findCard}
        />
      ))}
      <Icon type="plus" title="添加元素" onClick={addelement}/>
    </div>
  )
}
export default Container
src/menu/components/card/cardcellcomponent/dragaction/index.scss
New file
@@ -0,0 +1,32 @@
.card-detail-row {
  .ant-slider-track {
    height: 7px;
  }
  .ant-slider-rail {
    height: 7px;
  }
  .cyan {
    .ant-slider-track {
      background-color: #13C2C2;
    }
    .ant-slider-handle {
      border-color: #13C2C2;
    }
  }
  .orange {
    .ant-slider-track {
      background-color: orange;
    }
    .ant-slider-handle {
      border-color: lightsalmon;
    }
  }
  .primary {
    .ant-slider-track {
      background-color: #1890ff;
    }
    .ant-slider-handle {
      border-color: #91d5ff;
    }
  }
}
src/menu/components/card/cardcellcomponent/elementform/index.jsx
New file
@@ -0,0 +1,336 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import { fromJS } from 'immutable'
import { Form, Row, Col, Input, Select, Icon, Radio, Tooltip, InputNumber } from 'antd'
import { formRule } from '@/utils/option.js'
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'],
  icon: ['eleType', 'icon', 'fontSize', 'width', 'height', 'color', 'align', 'padding', 'tooltip'],
  slider: ['eleType', 'field', 'width', 'sildercolor', 'padding'],
  splitline: ['eleType', 'color', '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
              })
            }
          })
        }
        return item
      })
    })
  }
  getOptions = (eleType, datatype) => {
    let _options = fromJS(cardTypeOptions[eleType]).toJS() // 选项列表
    if (['text', 'number', 'picture'].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' || value === 'splitline') {
          if (this.props.form.getFieldValue('width') !== undefined) {
            this.props.form.setFieldsValue({width: 24})
          }
        }
      })
    } 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({
        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={0} max={10000} 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>
        )
      }
    })
    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
          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/cardcellcomponent/elementform/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/cardcellcomponent/formconfig.jsx
New file
@@ -0,0 +1,238 @@
// import zhCN from '@/locales/zh-CN/model.js'
// import enUS from '@/locales/en-US/model.js'
// const Formdict = localStorage.getItem('lang') !== 'en-US' ? zhCN : enUS
/**
 * @description 获取按钮表单配置信息
 * @param {*} card           编辑按钮
 * @param {*} setting        组件配置
 * @param {*} permFuncField  存储过程可用的开始字段
 * @param {*} type           按钮类型,用于区分可选的打开方式
 */
export function getCardCellForm (card) {
  let forms = [
    {
      type: 'select',
      key: 'eleType',
      label: '元素类型',
      initVal: card.eleType,
      required: true,
      options: [
        { value: 'text', text: '文本'},
        { value: 'number', text: '数值'},
        { value: 'picture', text: '图片'},
        { value: 'icon', text: '图标'},
        { value: 'slider', text: '进度条'},
        { value: 'splitline', text: '分割线'},
      ]
    },
    {
      type: 'radio',
      key: 'datatype',
      label: '数据类型',
      initVal: card.datatype || 'dynamic',
      required: true,
      options: [
        { value: 'dynamic', text: '动态' },
        { value: 'static', text: '静态' }
      ]
    },
    {
      type: 'select',
      key: 'field',
      label: '字段',
      initVal: card.field || '',
      required: true,
      options: []
    },
    {
      type: 'text',
      key: 'value',
      label: '内容',
      initVal: card.value || '',
      required: true
    },
    {
      type: 'text',
      key: 'prefix',
      label: '前缀',
      initVal: card.prefix || '',
      required: false
    },
    {
      type: 'text',
      key: 'postfix',
      label: '后缀',
      initVal: card.postfix || '',
      required: false
    },
    {
      type: 'select',
      key: 'icon',
      label: '图标',
      initVal: card.icon,
      required: true,
      options: [
        { value: 'question-circle', text: 'question-circle'},
        { value: 'alert', text: 'alert'},
        { value: 'cloud', text: 'cloud'},
        { value: 'eye', text: 'eye'},
        { value: 'eye-invisible', text: 'eye-invisible'},
        { value: 'android', text: 'android'},
        { value: 'apple', text: 'apple'},
        { value: 'windows', text: 'windows'},
        { value: 'ie', text: 'ie'},
        { value: 'chrome', text: 'chrome'},
        { value: 'github', text: 'github'},
        { value: 'aliwangwang', text: 'aliwangwang'},
        { value: 'dingding', text: 'dingding'},
        { value: 'wechat', text: 'wechat'},
        { value: 'alipay', text: 'alipay'},
        { value: 'weibo-square', text: 'weibo-square'},
        { value: 'weibo-circle', text: 'weibo-circle'},
        { value: 'taobao-circle', text: 'taobao-circle'},
        { value: 'weibo', text: 'weibo'},
        { value: 'twitter', text: 'twitter'},
        { value: 'youtube', text: 'youtube'},
        { value: 'alipay-circle', text: 'alipay-circle'},
        { value: 'taobao', text: 'taobao'},
        { value: 'skype', text: 'skype'},
        { value: 'qq', text: 'qq'},
        { value: 'gitlab', text: 'gitlab'},
        { value: 'zhihu', text: 'zhihu'},
        { value: 'slack', text: 'slack'},
        { value: 'sketch', text: 'sketch'},
        { value: 'yahoo', text: 'yahoo'},
        { value: 'reddit', text: 'reddit'},
        { value: 'dribbble', text: 'dribbble'},
      ]
    },
    {
      type: 'text',
      key: 'tooltip',
      label: '提示信息',
      initVal: card.tooltip || '',
      tooltip: '鼠标悬浮时显示。',
      required: false
    },
    {
      type: 'select',
      key: 'format',
      label: '格式化',
      initVal: card.format || '',
      tooltip: '注:百分数、千分位对于数值类型有效,YYYY-MM-DD对于时间类型的文本有效。',
      required: false,
      options: [
        { value: '', text: '无' },
        { value: 'percent', text: '百分数' },
        { value: 'thdSeparator', text: '千分位' },
        { value: 'YYYY-MM-DD', text: 'YYYY-MM-DD' }
      ]
    },
    {
      type: 'radio',
      key: 'align',
      label: '对齐方式',
      initVal: card.align || 'left',
      required: true,
      options: [
        { value: 'left', text: '左对齐' },
        { value: 'center', text: '居中' },
        { value: 'right', text: '右对齐' },
      ]
    },
    {
      type: 'number',
      key: 'fontSize',
      min: 12,
      max: 50,
      label: '字体大小',
      initVal: card.fontSize || 14,
      required: true,
    },
    {
      type: 'select',
      key: 'fontWeight',
      label: '字体粗细',
      initVal: card.fontWeight || 'normal',
      required: true,
      options: [
        { value: 'normal', text: '正常' },
        { value: 'bold', text: 'bold' },
        { value: 'bolder', text: 'bolder' },
        { value: 'lighter', text: 'lighter' },
        { value: '100', text: '100' },
        { value: '200', text: '200' },
        { value: '300', text: '300' },
        { value: '400', text: '400' },
        { value: '500', text: '500' },
        { value: '600', text: '600' },
        { value: '700', text: '700' },
        { value: '800', text: '800' },
        { value: '900', text: '900' }
      ]
    },
    {
      type: 'color',
      key: 'color',
      label: '颜色',
      initVal: card.color,
      required: false
    },
    {
      type: 'number',
      key: 'width',
      min: 1,
      max: 24,
      precision: 0,
      label: '宽度',
      initVal: card.width || 12,
      tooltip: '每行等分为24份。',
      required: true
    },
    {
      type: 'number',
      key: 'height',
      min: 1,
      max: 10,
      label: '高度(行)',
      initVal: card.height || 1,
      required: true,
    },
    {
      type: 'select',
      key: 'lenWidRadio',
      label: '长宽比',
      initVal: card.lenWidRadio || '1:1',
      required: true,
      options: [
        { value: '1:1', text: '1:1' },
        { value: '3:2', text: '3:2' },
        { value: '4:3', text: '4:3' },
        { value: '16:9', text: '16:9' }
      ]
    },
    {
      type: 'radio',
      key: 'radius',
      label: '圆角',
      initVal: card.radius || 'false',
      required: true,
      options: [
        { value: 'true', text: '有' },
        { value: 'false', text: '无' }
      ]
    },
    {
      type: 'text',
      key: 'padding',
      label: '内边距',
      initVal: card.padding,
      tooltip: '内边距需要按照固定格式填写,例:5px(上下左右均为5像素),5px 10px(上下5像素,左右10像素),5px 10px 15px(上5像素,左右10像素,下15像素),5px 10px 5px 10px(上5像素,右10像素,下5像素,左10像素)',
      required: false
    },
  ]
  return forms
}
src/menu/components/card/cardcellcomponent/index.jsx
New file
@@ -0,0 +1,188 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import { is, fromJS } from 'immutable'
import { Modal } from 'antd'
import zhCN from '@/locales/zh-CN/model.js'
import enUS from '@/locales/en-US/model.js'
import { getCardCellForm } from './formconfig'
import ElementForm from './elementform'
import DragElement from './dragaction'
import './index.scss'
const { confirm } = Modal
class CardCellComponent extends Component {
  static propTpyes = {
    config: PropTypes.object,        // 菜单配置信息
    updateElement: PropTypes.func     // 菜单配置更新
  }
  state = {
    dict: localStorage.getItem('lang') !== 'en-US' ? zhCN : enUS,
    card: null,          // 编辑中元素
    formlist: null,      // 表单信息
    elements: null,      // 按钮组
    visible: false,      // 模态框控制
  }
  /**
   * @description 搜索条件初始化
   */
  UNSAFE_componentWillMount () {
    const { config } = this.props
    this.setState({
      elements: fromJS(config.elements).toJS()
    })
  }
  /**
   * @description 按钮顺序调整,或拖拽添加
   */
  handleList = (list, card) => {
    const { config } = this.props
    if (card) {
      this.setState({elements: list})
      this.handleElement(card)
    } else {
      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() {}
    })
  }
  shouldComponentUpdate (nextProps, nextState) {
    return !is(fromJS(this.props.config), fromJS(nextProps.config)) || !is(fromJS(this.state), fromJS(nextState))
  }
  /**
   * @description 组件销毁,清除state更新
   */
  componentWillUnmount () {
    this.setState = () => {
      return
    }
  }
  render() {
    const { config } = this.props
    const { elements, visible, card, dict } = this.state
    return (
      <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 CardCellComponent
src/menu/components/card/cardcellcomponent/index.scss
New file
@@ -0,0 +1,28 @@
.model-menu-card-cell-list {
  min-height: calc(100% - 50px);
  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 {
  //   box-sizing: content-box;
  // }
  .card-cell:hover {
    box-shadow: 0px 0px 1px #d8d8d8;
  }
  .ant-slider {
    margin: 0px;
  }
}
src/menu/components/card/data-card/index.jsx
@@ -15,6 +15,7 @@
const SettingComponent = asyncIconComponent(() => import('@/menu/datasource'))
const WrapComponent = asyncIconComponent(() => import('./wrapsetting'))
const ActionComponent = asyncComponent(() => import('@/menu/actioncomponent'))
const CardCellComponent = asyncComponent(() => import('../cardcellcomponent'))
class antvBarLineChart extends Component {
  static propTpyes = {
@@ -117,13 +118,8 @@
          <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'}}>
          <ActionComponent
            config={card}
            tabs={[]}
            // setSubConfig={(_btn) => this.setSubConfig(_btn, 'button')}
            updateaction={this.updateComponent}
          />
          <CardCellComponent config={card} updateElement={this.updateComponent}/>
          <ActionComponent config={card} updateaction={this.updateComponent}/>
        </div>
      </div>
    )
src/menu/components/card/data-card/index.scss
@@ -22,6 +22,21 @@
  .card-item:hover {
    box-shadow: 0px 0px 2px #e8e8e8;
  }
  .model-menu-card-cell-list .card-detail-row > .anticon-plus {
    position: absolute;
    right: -30px;
    font-size: 16px;
  }
  .model-menu-action-list {
    min-height: 40px;
    line-height: 40px;
    .ant-row > .anticon-plus {
      position: absolute;
      right: -30px;
      font-size: 16px;
    }
  }
}
.menu-data-card-edit-box::after {
  display: block;
src/menu/datasource/verifycard/utils.jsx
@@ -7,7 +7,7 @@
   * @return {Object}  setting       页面设置
   * @return {Array}   columns       显示字段
   */
  static getDebugSql (setting, scripts, columns, searches) {
  static getDebugSql (setting, scripts, columns, searches = []) {
    let sql = ''
    let _dataresource = ''
    let _customScript = ''
src/mob/colorsketch/index.jsx
@@ -8,16 +8,16 @@
class ColorSketch extends Component {
  static propTpyes = {
    color: PropTypes.any,
    changeColor: PropTypes.func
    value: PropTypes.any,
    onChange: PropTypes.func
  }
  state = {
    color: this.props.color,
    color: this.props.value,
  }
  handleChange = (color) => {
    this.setState({ color: color.rgb })
    this.props.changeColor(`rgba(${ color.rgb.r }, ${ color.rgb.g }, ${ color.rgb.b }, ${ color.rgb.a })`)
    this.props.onChange(`rgba(${ color.rgb.r }, ${ color.rgb.g }, ${ color.rgb.b }, ${ color.rgb.a })`)
  }
  render() {
@@ -31,13 +31,14 @@
    }
    return (
      <div className="color-sketch-block">
      <Popover content={
        <SketchPicker color={ this.state.color } onChange={ this.handleChange } />
      } overlayClassName="color-sketch-popover" placement="bottomRight" title="" trigger="click">
        <div className="color-sketch-block">
          <div className="color-sketch-block-inner" style={ {background: _color} }></div>
        </div>
      </Popover>
        <div className="color-sketch-value">{_color}</div>
      </div>
    )
  }
}
src/mob/colorsketch/index.scss
@@ -1,19 +1,30 @@
.color-sketch-block {
  padding: 5px;
  background: #fff;
  border-radius: 2px;
  box-shadow: 0 0 0 1px rgba(0, 0, 0, .1);
  display: inline-block;
  cursor: pointer;
  height: 25px;
  width: 100%;
  .color-sketch-block-inner {
    width: 50px;
    height: 14px;
    display: inline-block;
    cursor: pointer;
    border-radius: 2px;
    box-shadow: 0 0 0 1px rgba(0, 0, 0, .1);
    width: calc(100% - 170px);
    height: 100%;
    border-radius: 2px;
  }
  .color-sketch-value {
    display: inline-block;
    width: 170px;
    padding-left: 10px;
    height: 25px;
    line-height: 25px;
    vertical-align: top;
    white-space: nowrap;
    overflow: visible;
  }
}
.color-sketch-popover {
  z-index: 1090!important;
  .ant-popover-inner-content {
    padding: 0;
    .sketch-picker {
src/mob/controller/index.jsx
@@ -315,7 +315,7 @@
                  label={<Icon title="字体颜色" type="font-colors" />}
                  labelCol={{xs: { span: 24 }, sm: { span: 4 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 20 }} }
                >
                  <ColorSketch color={card.color || '#000000'} changeColor={this.changeFontColor} />
                  <ColorSketch value={card.color || '#000000'} onChange={this.changeFontColor} />
                  <Input value={fontColor} onChange={this.changeFontColorInput} />
                </Form.Item>
              </Col>
src/templates/sharecomponent/actioncomponent/index.jsx
@@ -856,14 +856,6 @@
    const { config, type, menu } = this.props
    this.actionFormRef.handleConfirm().then(result => {
      if (result.Ot === 'requiredOnce') {
        notification.warning({
          top: 92,
          message: '多行拼接时,不可创建接口!',
          duration: 5
        })
        return
      }
      let _menu = {
        type: type,
        MenuID: menu.MenuID,
@@ -907,11 +899,6 @@
    const { config } = this.props
    const { actionlist, visible, card, dict, copying, profVisible } = this.state
    let hasbtncrtinter = false
    if (card && !card.copyType && config.setting.interType === 'system' && config.setting.dataresource) {
      hasbtncrtinter = true
    }
    return (
      <div className="model-table-action-list" style={config.charts.length > 1 ? {paddingTop: 25} : null}>
        <Tooltip placement="bottomLeft" overlayClassName="middle" title={dict['model.tooltip.action.guide']}>
@@ -935,8 +922,8 @@
          maskClosable={false}
          onCancel={this.editModalCancel}
          footer={[
            hasbtncrtinter ? <CreateInterface key="interface" dict={dict} ref="btnCreatInterface" trigger={this.btnCreatInterface}/> : null,
            card && !card.copyType ? <CreateFunc key="create" dict={dict} ref="btnCreatFunc" trigger={this.creatFunc}/> : null,
            <CreateInterface key="interface" dict={dict} ref="btnCreatInterface" trigger={this.btnCreatInterface}/>,
            <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>
          ]}
src/templates/zshare/createinterface/index.jsx
@@ -314,7 +314,7 @@
    if (!['pop', 'exec', 'prompt'].includes(btn.OpenType) || btn.funcType || btn.intertype !== 'system') {
      notification.warning({
        top: 92,
        message: '打开方式为 弹窗(表单)、提示框或直接执行,且使用系统函数时,才可以创建接口!',
        message: '打开方式为 弹窗(表单)、提示框或直接执行,且接口类型为系统时,才可以创建接口!',
        duration: 5
      })
      return
src/utils/option.js
@@ -200,7 +200,7 @@
// 按钮图标集
export const btnIcons = [{
  value: '',
  text: 'unset'
  text: '无'
}, {
  value: 'plus',
  text: 'plus'