king
2022-05-27 43398618f35eb084ed4eb4000bd2e082196cbf71
错误信息收集&注释btnlog
32个文件已修改
2998 ■■■■■ 已修改文件
src/menu/components/card/balcony/index.jsx 112 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/card/cardcellcomponent/formconfig.jsx 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/card/cardcellcomponent/index.jsx 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/card/data-card/index.jsx 273 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/card/prop-card/index.jsx 320 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/card/table-card/index.jsx 234 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/carousel/data-card/index.jsx 184 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/carousel/prop-card/index.jsx 244 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/chart/antv-bar/index.jsx 138 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/chart/antv-dashboard/index.jsx 77 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/chart/antv-pie/index.jsx 94 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/chart/antv-scatter/index.jsx 124 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/chart/chart-custom/index.jsx 65 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/code/sandbox/index.jsx 66 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/editor/braft-editor/index.jsx 56 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/form/normal-form/index.jsx 79 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/form/tab-form/index.jsx 83 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/module/voucher/index.jsx 35 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/table/edit-table/index.jsx 140 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/table/normal-table/index.jsx 258 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/timeline/normal-timeline/index.jsx 85 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/tree/antd-tree/index.jsx 64 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/popview/index.jsx 32 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/stylecontroller/index.jsx 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pc/components/login/normal-login/index.jsx 45 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/appmanage/scriptform/index.jsx 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/menudesign/index.jsx 45 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/menudesign/index.scss 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mobdesign/index.jsx 35 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mobdesign/index.scss 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/pcdesign/index.jsx 45 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/pcdesign/index.scss 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/card/balcony/index.jsx
@@ -72,10 +72,8 @@
          return elem
        })
      }
      this.setState({
        card: _card
      })
      this.props.updateConfig(_card)
      this.updateComponent(_card)
    } else {
      this.setState({
        card: fromJS(card).toJS()
@@ -104,15 +102,82 @@
  /**
   * @description 卡片行外层信息更新(数据源,样式等)
   */
  updateComponent = (component) => {
  updateComponent = (card) => {
    card.width = card.wrap.width
    card.name = card.wrap.name
    card.btnlog = []
    if (window.GLOB.styling && card.errors) { // 样式修改时不做筛查
      this.setState({
        card: card
      })
      this.props.updateConfig(card)
      return
    }
    card.errors = []
    if (card.wrap.datatype === 'static') {
      let supModule = card.wrap.linkType === 'static' ? '' : 'has'
      card.elements.forEach(cell => {
        if (cell.eleType === 'button') {
          if (cell.OpenType === 'pop' || (cell.OpenType === 'funcbutton' && cell.execMode === 'pop')) {
            if (!cell.modal || cell.modal.fields.length === 0) {
              card.errors.push({ level: 1, detail: `按钮“${cell.label}”中表单尚未添加`})
            } else if (!supModule) {
              cell.modal.fields.forEach(m => {
                if (m.type === 'linkMain') {
                  card.errors.push({ level: 1, detail: `按钮“${cell.label}”中关联主表表单“${m.label}”无效`})
                }
              })
            }
          }
        } else if (cell.datatype === 'dynamic' && cell.field) {
          card.errors.push({ level: 1, detail: `卡片中动态字段“${cell.field}”无效`})
        }
      })
    } else {
      if (card.setting.interType === 'system' && card.setting.execute !== 'false' && !card.setting.dataresource) {
        card.errors.push({ level: 0, detail: '未设置数据源!'})
      } else if (card.setting.interType === 'system' && card.setting.execute === 'false' && card.scripts.filter(script => script.status !== 'false').length === 0) {
        card.errors.push({ level: 0, detail: '数据源中无可用脚本!'})
      } else if (!card.setting.primaryKey) {
        card.errors.push({ level: 0, detail: '未设置主键!'})
      }
      let supModule = card.wrap.linkType === 'static' ? '' : 'has'
      let columns = card.columns.map(c => c.field)
      let lowcols = card.columns.map(c => c.field.toLowerCase())
      card.elements.forEach(cell => {
        if (cell.eleType === 'button') {
          if (cell.OpenType === 'pop' || (cell.OpenType === 'funcbutton' && cell.execMode === 'pop')) {
            if (!cell.modal || cell.modal.fields.length === 0) {
              card.errors.push({ level: 1, detail: `按钮“${cell.label}”中表单尚未添加`})
            } else {
              cell.modal.fields.forEach(m => {
                if (m.type === 'linkMain' && !supModule) {
                  card.errors.push({ level: 1, detail: `按钮“${cell.label}”中关联主表表单“${m.label}”无效`})
                } else if (m.field && card.wrap.linkType !== 'sync' && !columns.includes(m.field) && lowcols.includes(m.field.toLowerCase())) {
                  card.errors.push({ level: 1, detail: `按钮“${cell.label}”中表单“${m.label}”大小写与字段集不一致`})
                }
              })
            }
          }
        } else if (cell.datatype === 'dynamic' && cell.field && !columns.includes(cell.field)) {
          card.errors.push({ level: 1, detail: `卡片中动态字段“${cell.field}”无效`})
        }
      })
    }
    this.setState({
      card: component
      card: card
    })
    component.width = component.wrap.width
    component.name = component.wrap.name
    this.props.updateConfig(component)
    this.props.updateConfig(card)
  }
  updateCard = (elements) => {
@@ -120,11 +185,7 @@
    let _card = {...card, elements: elements}
    this.setState({
      card: _card,
    })
    this.props.updateConfig(_card)
    this.updateComponent(_card)
  }
  changeStyle = () => {
@@ -140,11 +201,7 @@
    let _card = {...card, style}
    this.setState({
      card: _card
    })
    this.props.updateConfig(_card)
    this.updateComponent(_card)
  }
  addElement = () => {
@@ -230,7 +287,20 @@
        </Popover>
        {card.wrap.checkAll === 'show' ? <div className="check-all"><Checkbox>全选</Checkbox></div> : null}
        <CardCellComponent cards={card} cardCell={card} elements={card.elements} updateElement={this.updateCard}/>
        <div className="component-name"><div className="center">{card.name}</div></div>
        <div className="component-name">
          <div className="center">
            <div className="title">{card.name}</div>
            <div className="content">
              {card.errors && card.errors.map((err, index) => {
                if (err.level === 0) {
                  return <span key={index} className="error">{err.detail}</span>
                } else {
                  return <span key={index} className="waring">{err.detail};</span>
                }
              })}
            </div>
          </div>
        </div>
      </div>
    )
  }
src/menu/components/card/cardcellcomponent/formconfig.jsx
@@ -43,16 +43,8 @@
    }
  }
  let dataTypes = [
    { value: 'dynamic', text: '动态' },
    { value: 'static', text: '静态' }
  ]
  let tooltip = ''
  if (cardCell.$cardType === 'extendCard') {
    // card.datatype = 'static'
    // dataTypes = [
    //   { value: 'static', text: '静态' }
    // ]
    tooltip = '在扩展卡片中,动态数据显示值为获取到的第一行数据。'
  }
@@ -79,7 +71,10 @@
      initVal: card.datatype || 'static',
      tooltip,
      required: true,
      options: dataTypes
      options: [
        { value: 'dynamic', text: '动态' },
        { value: 'static', text: '静态' }
      ]
    },
    {
      type: 'select',
src/menu/components/card/cardcellcomponent/index.jsx
@@ -458,7 +458,7 @@
   * @description 按钮删除
   */
  deleteElement = (card) => {
    const { cards, cardCell, side } = this.props
    const { cardCell, side } = this.props
    const { dict, elements, appType } = this.state
    let _this = this
@@ -471,7 +471,7 @@
          card.$parentId = cardCell.uuid
          card.$side = side || ''
          MKEmitter.emit('logButton', cards.uuid, card)
          // MKEmitter.emit('logButton', cards.uuid, card)
        }
        _this.setState({
src/menu/components/card/data-card/index.jsx
@@ -1,7 +1,7 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import { is, fromJS } from 'immutable'
import { Popover, Modal, Pagination, notification } from 'antd'
import { Popover, Modal, Pagination } from 'antd'
import { PlusOutlined, PlusCircleOutlined, PlusSquareOutlined, EditOutlined, ToolOutlined, DeleteOutlined, FontColorsOutlined } from '@ant-design/icons'
import asyncComponent from '@/utils/asyncComponent'
@@ -16,7 +16,7 @@
const NormalForm = asyncIconComponent(() => import('@/components/normalform'))
const CardComponent = asyncComponent(() => import('../cardcomponent'))
const MobPagination = asyncIconComponent(() => import('@/menu/components/share/mobPagination'))
const LogComponent = asyncIconComponent(() => import('@/menu/components/share/logcomponent'))
// const LogComponent = asyncIconComponent(() => import('@/menu/components/share/logcomponent'))
const CopyComponent = asyncIconComponent(() => import('@/menu/components/share/copycomponent'))
const UserComponent = asyncIconComponent(() => import('@/menu/components/share/usercomponent'))
const PasteComponent = asyncIconComponent(() => import('@/components/paste'))
@@ -113,10 +113,7 @@
        })
      }
      this.setState({
        card: _card
      })
      this.props.updateConfig(_card)
      this.updateComponent(_card)
    } else {
      let _card = fromJS(card).toJS()
      _card.action = _card.action || [] // 兼容
@@ -150,7 +147,7 @@
  componentDidMount () {
    MKEmitter.addListener('submitStyle', this.getStyle)
    MKEmitter.addListener('submitModal', this.handleSave)
    MKEmitter.addListener('logButton', this.logButton)
    // MKEmitter.addListener('logButton', this.logButton)
  }
  shouldComponentUpdate (nextProps, nextState) {
@@ -166,35 +163,142 @@
    }
    MKEmitter.removeListener('submitStyle', this.getStyle)
    MKEmitter.removeListener('submitModal', this.handleSave)
    MKEmitter.removeListener('logButton', this.logButton)
    // MKEmitter.removeListener('logButton', this.logButton)
  }
  logButton = (id, item) => {
    const { card } = this.state
  // logButton = (id, item) => {
  //   const { card } = this.state
    if (id !== card.uuid) return
  //   if (id !== card.uuid) return
    let btnlog = card.btnlog || []
    btnlog.push(item)
  //   let btnlog = card.btnlog || []
  //   btnlog.push(item)
    this.setState({
      card: {...card, btnlog}
    })
    this.props.updateConfig({...card, btnlog})
  }
  //   this.updateComponent({...card, btnlog})
  // }
  
  /**
   * @description 卡片行外层信息更新(数据源,样式等)
   */
  updateComponent = (component) => {
    this.setState({
      card: component
  updateComponent = (card) => {
    const { appType } = this.state
    card.width = card.wrap.width
    card.name = card.wrap.name
    card.btnlog = []
    if (window.GLOB.styling && card.errors) { // 样式修改时不做筛查
      this.setState({
        card: card
      })
      this.props.updateConfig(card)
      return
    }
    card.errors = []
    if (card.setting.interType === 'system' && card.setting.execute !== 'false' && !card.setting.dataresource) {
      card.errors.push({ level: 0, detail: '未设置数据源!'})
    } else if (card.setting.interType === 'system' && card.setting.execute === 'false' && card.scripts.filter(script => script.status !== 'false').length === 0) {
      card.errors.push({ level: 0, detail: '数据源中无可用脚本!'})
    } else if (!card.setting.primaryKey) {
      card.errors.push({ level: 0, detail: '未设置主键!'})
    } else if (!card.setting.supModule) {
      card.errors.push({ level: 0, detail: '未设置上级组件!'})
    }
    let supModule = ''
    if (card.wrap.supType === 'multi') { // 数据卡多上级组件
      if (card.supNodes && card.supNodes[0]) {
        supModule = card.supNodes[0].componentId
      }
    } else if (card.setting.supModule) {
      supModule = card.setting.supModule[card.setting.supModule.length - 1] || ''
      if (supModule === 'empty') {
        supModule = ''
      }
    }
    let columns = card.columns.map(c => c.field)
    let lowcols = card.columns.map(c => c.field.toLowerCase())
    card.action.forEach(cell => {
      if (cell.OpenType === 'pop' || (cell.OpenType === 'funcbutton' && cell.execMode === 'pop')) {
        if (!cell.modal || cell.modal.fields.length === 0) {
          card.errors.push({ level: 1, detail: `按钮“${cell.label}”中表单尚未添加`})
        } else {
          cell.modal.fields.forEach(m => {
            if (m.type === 'linkMain' && !supModule) {
              card.errors.push({ level: 1, detail: `按钮“${cell.label}”中关联主表表单“${m.label}”无效`})
            } else if (m.field && !columns.includes(m.field) && lowcols.includes(m.field.toLowerCase())) {
              card.errors.push({ level: 1, detail: `按钮“${cell.label}”中表单“${m.label}”大小写与字段集不一致`})
            }
          })
        }
      }
    })
    component.width = component.wrap.width
    component.name = component.wrap.name
    card.subcards.forEach((item, i) => {
      let linkbtn = item.setting.linkbtn || ''
      item.elements.forEach(cell => {
        if (cell.eleType === 'button') {
          if (cell.OpenType === 'pop' || (cell.OpenType === 'funcbutton' && cell.execMode === 'pop')) {
            if (!cell.modal || cell.modal.fields.length === 0) {
              card.errors.push({ level: 1, detail: `按钮“${cell.label}”中表单尚未添加`})
            } else {
              cell.modal.fields.forEach(m => {
                if (m.type === 'linkMain' && !supModule) {
                  card.errors.push({ level: 1, detail: `按钮“${cell.label}”中关联主表表单“${m.label}”无效`})
                } else if (m.field && !columns.includes(m.field) && lowcols.includes(m.field.toLowerCase())) {
                  card.errors.push({ level: 1, detail: `按钮“${cell.label}”中表单“${m.label}”大小写与字段集不一致`})
                }
              })
            }
          }
          if (linkbtn && linkbtn === cell.uuid) {
            linkbtn = ''
          }
        } else if (cell.datatype === 'dynamic' && cell.field && !columns.includes(cell.field)) {
          card.errors.push({ level: 1, detail: `卡片中动态字段“${cell.field}”无效`})
        }
      })
    this.props.updateConfig(component)
      if (item.setting.type === 'multi' && appType !== 'mob') {
        item.backElements.forEach(cell => {
          if (cell.eleType === 'button') {
            if (cell.OpenType === 'pop' || (cell.OpenType === 'funcbutton' && cell.execMode === 'pop')) {
              if (!cell.modal || cell.modal.fields.length === 0) {
                card.errors.push({ level: 1, detail: `按钮“${cell.label}”中表单尚未添加`})
              } else {
                cell.modal.fields.forEach(m => {
                  if (m.type === 'linkMain' && !supModule) {
                    card.errors.push({ level: 1, detail: `按钮“${cell.label}”中关联主表表单“${m.label}”无效`})
                  } else if (m.field && !columns.includes(m.field) && lowcols.includes(m.field.toLowerCase())) {
                    card.errors.push({ level: 1, detail: `按钮“${cell.label}”中表单“${m.label}”大小写与字段集不一致`})
                  }
                })
              }
            }
            if (linkbtn && linkbtn === cell.uuid) {
              linkbtn = ''
            }
          } else if (cell.datatype === 'dynamic' && cell.field && !columns.includes(cell.field)) {
            card.errors.push({ level: 1, detail: `卡片中动态字段“${cell.field}”无效`})
          }
        })
      }
      if (linkbtn) {
        card.errors.push({ level: 1, detail: `第${i + 1}张卡片中绑定按钮已删除`})
      }
    })
    this.setState({
      card: card
    })
    this.props.updateConfig(card)
  }
  /**
@@ -212,9 +316,7 @@
      card.action = card.action.filter(item => item.uuid !== btn.uuid)
    }
    this.setState({card})
    this.props.updateConfig(card)
    this.updateComponent(card)
  }
  /**
@@ -230,12 +332,11 @@
      onOk() {
        card.subcards = card.subcards.filter(item => item.uuid !== cell.uuid)
        if (card.btnlog) {
          card.btnlog = card.btnlog.filter(c => c.$parentId !== cell.uuid)
        }
        // if (card.btnlog) {
        //   card.btnlog = card.btnlog.filter(c => c.$parentId !== cell.uuid)
        // }
        _this.setState({card})
        _this.props.updateConfig(card)
        _this.updateComponent(card)
        if (appType === 'mob') return
@@ -272,12 +373,8 @@
    if (comIds.length !== 1 || comIds[0] !== card.uuid) return
    let _card = {...card, style}
    this.setState({
      card: _card
    })
    
    this.props.updateConfig(_card)
    this.updateComponent(_card)
  }
  addSearch = (copy) => {
@@ -373,52 +470,49 @@
      return cell
    })
    this.setState({card})
    this.props.updateConfig(card)
    this.updateComponent(card)
  }
  handleLog = (type, logs, item) => {
    let card = fromJS(this.state.card).toJS()
  // handleLog = (type, logs, item) => {
  //   let card = fromJS(this.state.card).toJS()
    if (type === 'revert') {
      let done = false
      if (item.$parentId) {
        card.subcards.forEach(col => {
          if (item.$parentId === col.uuid) {
            if (item.$side !== 'back') {
              col.elements = col.elements ? [...col.elements, item] : [item]
            } else {
              col.backElements = col.backElements ? [...col.backElements, item] : [item]
            }
            done = true
          }
        })
      }
  //   if (type === 'revert') {
  //     let done = false
  //     if (item.$parentId) {
  //       card.subcards.forEach(col => {
  //         if (item.$parentId === col.uuid) {
  //           if (item.$side !== 'back') {
  //             col.elements = col.elements ? [...col.elements, item] : [item]
  //           } else {
  //             col.backElements = col.backElements ? [...col.backElements, item] : [item]
  //           }
  //           done = true
  //         }
  //       })
  //     }
      if (!done) {
        card.action = card.action ? [...card.action, item] : [item]
      }
  //     if (!done) {
  //       card.action = card.action ? [...card.action, item] : [item]
  //     }
      card.btnlog = logs
  //     card.btnlog = logs
      this.setState({ card })
      this.props.updateConfig(card)
      notification.success({
        top: 92,
        message: '恢复成功!',
        duration: 2
      })
    } else {
      card.btnlog = logs
      this.setState({ card })
      this.props.updateConfig(card)
      notification.success({
        top: 92,
        message: '清除成功!',
        duration: 2
      })
    }
  }
  //     this.updateComponent(card)
  //     notification.success({
  //       top: 92,
  //       message: '恢复成功!',
  //       duration: 2
  //     })
  //   } else {
  //     card.btnlog = logs
  //     this.updateComponent(card)
  //     notification.success({
  //       top: 92,
  //       message: '清除成功!',
  //       duration: 2
  //     })
  //   }
  // }
  addCard = (copy) => {
    let card = fromJS(this.state.card).toJS()
@@ -449,9 +543,8 @@
    }
    card.subcards.push(newcard)
    this.setState({card})
    this.props.updateConfig(card)
    this.updateComponent(card)
  }
  move = (item, direction) => {
@@ -470,8 +563,7 @@
    card.subcards.splice(hoverIndex, 0, ...card.subcards.splice(dragIndex, 1))
    this.setState({card})
    this.props.updateConfig(card)
    this.updateComponent(card)
  }
  getWrapForms = () => {
@@ -659,7 +751,7 @@
            <CopyComponent type="datacard" card={card}/>
            <PasteComponent options={['action', 'search', 'form', 'cardcell']} updateConfig={this.pasteComponent} />
            <FontColorsOutlined className="style" title="调整样式" onClick={this.changeStyle}/>
            <LogComponent btnlog={card.btnlog || []} handlelog={this.handleLog} />
            {/* <LogComponent btnlog={card.btnlog || []} handlelog={this.handleLog} /> */}
            <UserComponent config={card}/>
            <DeleteOutlined className="close" title="删除组件" onClick={() => this.props.deletecomponent(card.uuid)} />
            <SettingComponent config={card} updateConfig={this.updateComponent} />
@@ -674,7 +766,20 @@
        <div style={{clear: 'both'}}></div>
        {card.wrap.pagestyle === 'page' && card.setting.laypage === 'true' && appType !== 'mob' ? <Pagination total={85} size="small" showTotal={total => `共 ${total} 条`} pageSize={20} defaultCurrent={1}/> : null}
        {card.wrap.pagestyle === 'page' && card.setting.laypage === 'true' && appType === 'mob' ? <MobPagination /> : null}
        <div className="component-name"><div className="center">{card.name}</div></div>
        <div className="component-name">
          <div className="center">
            <div className="title">{card.name}</div>
            <div className="content">
              {card.errors && card.errors.map((err, index) => {
                if (err.level === 0) {
                  return <span key={index} className="error">{err.detail}</span>
                } else {
                  return <span key={index} className="waring">{err.detail};</span>
                }
              })}
            </div>
          </div>
        </div>
      </div>
    )
  }
src/menu/components/card/prop-card/index.jsx
@@ -1,7 +1,7 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import { is, fromJS } from 'immutable'
import { Popover, Modal, notification } from 'antd'
import { Popover, Modal } from 'antd'
import { PlusOutlined, SettingOutlined, EditOutlined, ToolOutlined, DeleteOutlined, FontColorsOutlined } from '@ant-design/icons'
import asyncComponent from '@/utils/asyncComponent'
@@ -17,7 +17,7 @@
const CardComponent = asyncComponent(() => import('../cardcomponent'))
const CopyComponent = asyncIconComponent(() => import('@/menu/components/share/copycomponent'))
const PasteComponent = asyncIconComponent(() => import('@/components/paste'))
const LogComponent = asyncIconComponent(() => import('@/menu/components/share/logcomponent'))
// const LogComponent = asyncIconComponent(() => import('@/menu/components/share/logcomponent'))
const UserComponent = asyncIconComponent(() => import('@/menu/components/share/usercomponent'))
const ClockComponent = asyncIconComponent(() => import('@/menu/components/share/clockcomponent'))
const NormalHeader = asyncComponent(() => import('@/menu/components/share/normalheader'))
@@ -100,10 +100,7 @@
          return scard
        })
      }
      this.setState({
        card: _card
      })
      this.props.updateConfig(_card)
      this.updateComponent(_card)
    } else {
      this.setState({
        card: fromJS(card).toJS()
@@ -113,7 +110,7 @@
  componentDidMount () {
    MKEmitter.addListener('submitStyle', this.getStyle)
    MKEmitter.addListener('logButton', this.logButton)
    // MKEmitter.addListener('logButton', this.logButton)
    MKEmitter.addListener('submitComponentStyle', this.updateComponentStyle)
  }
@@ -129,7 +126,7 @@
      return
    }
    MKEmitter.removeListener('submitStyle', this.getStyle)
    MKEmitter.removeListener('logButton', this.logButton)
    // MKEmitter.removeListener('logButton', this.logButton)
    MKEmitter.removeListener('submitComponentStyle', this.updateComponentStyle)
  }
@@ -150,32 +147,175 @@
    })
  }
  logButton = (id, item) => {
    const { card } = this.state
  // 按钮历史记录
  // logButton = (id, item) => {
  //   const { card } = this.state
    if (id !== card.uuid) return
  //   if (id !== card.uuid) return
    let btnlog = card.btnlog || []
    btnlog.push(item)
  //   let btnlog = card.btnlog || []
  //   btnlog.push(item)
    this.setState({
      card: {...card, btnlog}
    })
    this.props.updateConfig({...card, btnlog})
  }
  //   this.updateComponent({...card, btnlog})
  // }
  /**
   * @description 卡片行外层信息更新(数据源,样式等)
   */
  updateComponent = (component) => {
  updateComponent = (card) => {
    const { appType } = this.state
    card.width = card.wrap.width
    card.name = card.wrap.name
    card.btnlog = []
    if (window.GLOB.styling && card.errors) { // 样式修改时不做筛查
      this.setState({
        card: card
      })
      this.props.updateConfig(card)
      return
    }
    card.errors = []
    if (card.subcards.length === 0) {
      card.errors.push({ level: 0, detail: '卡片不可为空!'})
    }
    if (card.wrap.datatype === 'static') {
      let supModule = card.wrap.supModule ? card.wrap.supModule[card.wrap.supModule.length - 1] : ''
      card.subcards.forEach((item, i) => {
        let linkbtn = item.setting.linkbtn || ''
        item.elements.forEach(cell => {
          if (cell.eleType === 'button') {
            if (cell.OpenType === 'pop' || (cell.OpenType === 'funcbutton' && cell.execMode === 'pop')) {
              if (!cell.modal || cell.modal.fields.length === 0) {
                card.errors.push({ level: 1, detail: `按钮“${cell.label}”中表单尚未添加`})
              } else if (!supModule) {
                cell.modal.fields.forEach(m => {
                  if (m.type === 'linkMain') {
                    card.errors.push({ level: 1, detail: `按钮“${cell.label}”中关联主表表单“${m.label}”无效`})
                  }
                })
              }
            }
            if (linkbtn && linkbtn === cell.uuid) {
              linkbtn = ''
            }
          } else if (cell.datatype === 'dynamic' && cell.field) {
            card.errors.push({ level: 1, detail: `卡片中动态字段“${cell.field}”无效`})
          }
        })
        if (item.setting.type === 'multi' && appType !== 'mob') {
          item.backElements.forEach(cell => {
            if (cell.eleType === 'button') {
              if (cell.OpenType === 'pop' || (cell.OpenType === 'funcbutton' && cell.execMode === 'pop')) {
                if (!cell.modal || cell.modal.fields.length === 0) {
                  card.errors.push({ level: 1, detail: `按钮“${cell.label}”中表单尚未添加`})
                } else if (!supModule) {
                  cell.modal.fields.forEach(m => {
                    if (m.type === 'linkMain') {
                      card.errors.push({ level: 1, detail: `按钮“${cell.label}”中关联主表表单“${m.label}”无效`})
                    }
                  })
                }
              }
              if (linkbtn && linkbtn === cell.uuid) {
                linkbtn = ''
              }
            } else if (cell.datatype === 'dynamic' && cell.field) {
              card.errors.push({ level: 1, detail: `卡片中动态字段“${cell.field}”无效`})
            }
          })
        }
        if (linkbtn) {
          card.errors.push({ level: 1, detail: `第${i + 1}张卡片中绑定按钮已删除`})
        }
      })
    } else {
      if (card.setting.interType === 'system' && card.setting.execute !== 'false' && !card.setting.dataresource) {
        card.errors.push({ level: 0, detail: '未设置数据源!'})
      } else if (card.setting.interType === 'system' && card.setting.execute === 'false' && card.scripts.filter(script => script.status !== 'false').length === 0) {
        card.errors.push({ level: 0, detail: '数据源中无可用脚本!'})
      } else if (!card.setting.primaryKey) {
        card.errors.push({ level: 0, detail: '未设置主键!'})
      } else if (!card.setting.supModule) {
        card.errors.push({ level: 0, detail: '未设置上级组件!'})
      }
      let supModule = card.setting.supModule ? card.setting.supModule[card.setting.supModule.length - 1] || '' : ''
      if (supModule === 'empty') {
        supModule = ''
      }
      let columns = card.columns.map(c => c.field)
      let lowcols = card.columns.map(c => c.field.toLowerCase())
      card.subcards.forEach((item, i) => {
        let linkbtn = item.setting.linkbtn || ''
        item.elements.forEach(cell => {
          if (cell.eleType === 'button') {
            if (cell.OpenType === 'pop' || (cell.OpenType === 'funcbutton' && cell.execMode === 'pop')) {
              if (!cell.modal || cell.modal.fields.length === 0) {
                card.errors.push({ level: 1, detail: `按钮“${cell.label}”中表单尚未添加`})
              } else {
                cell.modal.fields.forEach(m => {
                  if (m.type === 'linkMain' && !supModule) {
                    card.errors.push({ level: 1, detail: `按钮“${cell.label}”中关联主表表单“${m.label}”无效`})
                  } else if (m.field && !columns.includes(m.field) && lowcols.includes(m.field.toLowerCase())) {
                    card.errors.push({ level: 1, detail: `按钮“${cell.label}”中表单“${m.label}”大小写与字段集不一致`})
                  }
                })
              }
            }
            if (linkbtn && linkbtn === cell.uuid) {
              linkbtn = ''
            }
          } else if (cell.datatype === 'dynamic' && cell.field && !columns.includes(cell.field)) {
            card.errors.push({ level: 1, detail: `卡片中动态字段“${cell.field}”无效`})
          }
        })
        if (item.setting.type === 'multi' && appType !== 'mob') {
          item.backElements.forEach(cell => {
            if (cell.eleType === 'button') {
              if (cell.OpenType === 'pop' || (cell.OpenType === 'funcbutton' && cell.execMode === 'pop')) {
                if (!cell.modal || cell.modal.fields.length === 0) {
                  card.errors.push({ level: 1, detail: `按钮“${cell.label}”中表单尚未添加`})
                } else {
                  cell.modal.fields.forEach(m => {
                    if (m.type === 'linkMain' && !supModule) {
                      card.errors.push({ level: 1, detail: `按钮“${cell.label}”中关联主表表单“${m.label}”无效`})
                    } else if (m.field && !columns.includes(m.field) && lowcols.includes(m.field.toLowerCase())) {
                      card.errors.push({ level: 1, detail: `按钮“${cell.label}”中表单“${m.label}”大小写与字段集不一致`})
                    }
                  })
                }
              }
              if (linkbtn && linkbtn === cell.uuid) {
                linkbtn = ''
              }
            } else if (cell.datatype === 'dynamic' && cell.field && !columns.includes(cell.field)) {
              card.errors.push({ level: 1, detail: `卡片中动态字段“${cell.field}”无效`})
            }
          })
        }
        if (linkbtn) {
          card.errors.push({ level: 1, detail: `第${i + 1}张卡片中绑定按钮已删除`})
        }
      })
    }
    this.setState({
      card: component
      card: card
    })
    component.width = component.wrap.width
    component.name = component.wrap.name
    this.props.updateConfig(component)
    this.props.updateConfig(card)
  }
  /**
@@ -189,9 +329,7 @@
      return item
    })
    this.setState({card})
    this.props.updateConfig(card)
    this.updateComponent(card)
  }
  /**
@@ -207,12 +345,11 @@
      onOk() {
        card.subcards = card.subcards.filter(item => item.uuid !== cell.uuid)
        if (card.btnlog) {
          card.btnlog = card.btnlog.filter(c => c.$parentId !== cell.uuid)
        }
        // if (card.btnlog) {
        //   card.btnlog = card.btnlog.filter(c => c.$parentId !== cell.uuid)
        // }
        _this.setState({card})
        _this.props.updateConfig(card)
        _this.updateComponent(card)
        if (appType === 'mob') return
@@ -249,12 +386,8 @@
    if (comIds.length !== 1 || comIds[0] !== card.uuid) return
    let _card = {...card, style}
    this.setState({
      card: _card
    })
    
    this.props.updateConfig(_card)
    this.updateComponent(_card)
  }
  addCard = (copy) => {
@@ -292,59 +425,56 @@
    }
    card.subcards.push(newcard)
    this.setState({card})
    this.props.updateConfig(card)
    this.updateComponent(card)
  }
  handleLog = (type, logs, item) => {
    let card = fromJS(this.state.card).toJS()
  // handleLog = (type, logs, item) => {
  //   let card = fromJS(this.state.card).toJS()
    if (type === 'revert') {
      let done = false
      if (item.$parentId) {
        card.subcards.forEach(col => {
          if (item.$parentId === col.uuid) {
            if (item.$side !== 'back') {
              col.elements = col.elements ? [...col.elements, item] : [item]
            } else {
              col.backElements = col.backElements ? [...col.backElements, item] : [item]
            }
            done = true
          }
        })
      }
  //   if (type === 'revert') {
  //     let done = false
  //     if (item.$parentId) {
  //       card.subcards.forEach(col => {
  //         if (item.$parentId === col.uuid) {
  //           if (item.$side !== 'back') {
  //             col.elements = col.elements ? [...col.elements, item] : [item]
  //           } else {
  //             col.backElements = col.backElements ? [...col.backElements, item] : [item]
  //           }
  //           done = true
  //         }
  //       })
  //     }
      card.btnlog = logs
  //     card.btnlog = logs
      this.setState({ card: {...card, subcards: []} }, () => {
        this.setState({ card })
        this.props.updateConfig(card)
      })
      if (!done) {
        notification.warning({
          top: 92,
          message: '附属卡片已删除!',
          duration: 2
        })
      } else {
        notification.success({
          top: 92,
          message: '恢复成功!',
          duration: 2
        })
      }
    } else {
      card.btnlog = logs
      this.setState({ card })
      this.props.updateConfig(card)
      notification.success({
        top: 92,
        message: '清除成功!',
        duration: 2
      })
    }
  }
  //     this.setState({ card: {...card, subcards: []} }, () => {
  //       this.updateComponent(card)
  //     })
  //     if (!done) {
  //       notification.warning({
  //         top: 92,
  //         message: '附属卡片已删除!',
  //         duration: 2
  //       })
  //     } else {
  //       notification.success({
  //         top: 92,
  //         message: '恢复成功!',
  //         duration: 2
  //       })
  //     }
  //   } else {
  //     card.btnlog = logs
  //     this.updateComponent(card)
  //     notification.success({
  //       top: 92,
  //       message: '清除成功!',
  //       duration: 2
  //     })
  //   }
  // }
  move = (item, direction) => {
    let card = fromJS(this.state.card).toJS()
@@ -362,8 +492,7 @@
    card.subcards.splice(hoverIndex, 0, ...card.subcards.splice(dragIndex, 1))
    this.setState({card})
    this.props.updateConfig(card)
    this.updateComponent(card)
  }
  pasteComponent = (res, resolve) => {
@@ -481,7 +610,7 @@
            <CopyComponent type="propcard" card={card}/>
            <PasteComponent options={['cardcell']} updateConfig={this.pasteComponent} />
            <FontColorsOutlined className="style" title="调整样式" onClick={this.changeStyle}/>
            <LogComponent btnlog={card.btnlog || []} handlelog={this.handleLog} />
            {/* <LogComponent btnlog={card.btnlog || []} handlelog={this.handleLog} /> */}
            <ClockComponent config={card} updateConfig={this.updateComponent}/>
            <UserComponent config={card}/>
            <DeleteOutlined className="close" title="删除组件" onClick={() => this.props.deletecomponent(card.uuid)} />
@@ -494,7 +623,20 @@
        <div className={(card.wrap.layout || 'grid') + '-layout float-' + (card.wrap.cardFloat || 'left')}>
          {card.subcards.map(subcard => (<CardComponent key={subcard.uuid} cards={card} card={subcard} move={this.move} updateElement={this.updateCard} deleteElement={this.deleteCard}/>))}
        </div>
        <div className="component-name"><div className="center">{card.name}</div></div>
        <div className="component-name">
          <div className="center">
            <div className="title">{card.name}</div>
            <div className="content">
              {card.errors && card.errors.map((err, index) => {
                if (err.level === 0) {
                  return <span key={index} className="error">{err.detail}</span>
                } else {
                  return <span key={index} className="waring">{err.detail};</span>
                }
              })}
            </div>
          </div>
        </div>
      </div>
    )
  }
src/menu/components/card/table-card/index.jsx
@@ -1,7 +1,7 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import { is, fromJS } from 'immutable'
import { Popover, Modal, Pagination, notification } from 'antd'
import { Popover, Modal, Pagination } from 'antd'
import { PlusOutlined, PlusCircleOutlined, PlusSquareOutlined, EditOutlined, ToolOutlined, DeleteOutlined, FontColorsOutlined } from '@ant-design/icons'
import asyncComponent from '@/utils/asyncComponent'
@@ -18,7 +18,7 @@
const MobPagination = asyncIconComponent(() => import('@/menu/components/share/mobPagination'))
const CopyComponent = asyncIconComponent(() => import('@/menu/components/share/copycomponent'))
const PasteComponent = asyncIconComponent(() => import('@/components/paste'))
const LogComponent = asyncIconComponent(() => import('@/menu/components/share/logcomponent'))
// const LogComponent = asyncIconComponent(() => import('@/menu/components/share/logcomponent'))
const UserComponent = asyncIconComponent(() => import('@/menu/components/share/usercomponent'))
const NormalHeader = asyncComponent(() => import('@/menu/components/share/normalheader'))
const ActionComponent = asyncComponent(() => import('@/menu/components/share/actioncomponent'))
@@ -104,10 +104,8 @@
          })
        }
      }
      this.setState({
        card: _card
      })
      this.props.updateConfig(_card)
      this.updateComponent(_card)
    } else {
      let _card = fromJS(card).toJS()
      if (!_card.action) {
@@ -140,7 +138,7 @@
  componentDidMount () {
    MKEmitter.addListener('submitStyle', this.getStyle)
    MKEmitter.addListener('logButton', this.logButton)
    // MKEmitter.addListener('logButton', this.logButton)
  }
  shouldComponentUpdate (nextProps, nextState) {
@@ -155,35 +153,95 @@
      return
    }
    MKEmitter.removeListener('submitStyle', this.getStyle)
    MKEmitter.removeListener('logButton', this.logButton)
    // MKEmitter.removeListener('logButton', this.logButton)
  }
  logButton = (id, item) => {
    const { card } = this.state
  // logButton = (id, item) => {
  //   const { card } = this.state
    if (id !== card.uuid) return
  //   if (id !== card.uuid) return
    let btnlog = card.btnlog || []
    btnlog.push(item)
  //   let btnlog = card.btnlog || []
  //   btnlog.push(item)
    this.setState({
      card: {...card, btnlog}
    })
    this.props.updateConfig({...card, btnlog})
  }
  //   this.updateComponent({...card, btnlog})
  // }
  /**
   * @description 卡片行外层信息更新(数据源,样式等)
   */
  updateComponent = (component) => {
    this.setState({
      card: component
  updateComponent = (card) => {
    card.width = card.wrap.width
    card.name = card.wrap.name
    card.btnlog = []
    if (window.GLOB.styling && card.errors) { // 样式修改时不做筛查
      this.setState({
        card: card
      })
      this.props.updateConfig(card)
      return
    }
    card.errors = []
    if (card.subcards.length === 0) {
      card.errors.push({ level: 0, detail: '卡片不可为空!'})
    }
    if (card.setting.interType === 'system' && card.setting.execute !== 'false' && !card.setting.dataresource) {
      card.errors.push({ level: 0, detail: '未设置数据源!'})
    } else if (card.setting.interType === 'system' && card.setting.execute === 'false' && card.scripts.filter(script => script.status !== 'false').length === 0) {
      card.errors.push({ level: 0, detail: '数据源中无可用脚本!'})
    } else if (!card.setting.primaryKey) {
      card.errors.push({ level: 0, detail: '未设置主键!'})
    } else if (!card.setting.supModule) {
      card.errors.push({ level: 0, detail: '未设置上级组件!'})
    }
    let supModule = card.setting.supModule ? card.setting.supModule[card.setting.supModule.length - 1] || '' : ''
    if (supModule === 'empty') {
      supModule = ''
    }
    let columns = card.columns.map(c => c.field)
    let lowcols = card.columns.map(c => c.field.toLowerCase())
    card.subcards.forEach((item, i) => {
      let linkbtn = item.setting.linkbtn || ''
      item.elements.forEach(cell => {
        if (cell.eleType === 'button') {
          if (cell.OpenType === 'pop' || (cell.OpenType === 'funcbutton' && cell.execMode === 'pop')) {
            if (!cell.modal || cell.modal.fields.length === 0) {
              card.errors.push({ level: 1, detail: `按钮“${cell.label}”中表单尚未添加`})
            } else {
              cell.modal.fields.forEach(m => {
                if (m.type === 'linkMain' && !supModule) {
                  card.errors.push({ level: 1, detail: `按钮“${cell.label}”中关联主表表单“${m.label}”无效`})
                } else if (m.field && !columns.includes(m.field) && lowcols.includes(m.field.toLowerCase())) {
                  card.errors.push({ level: 1, detail: `按钮“${cell.label}”中表单“${m.label}”大小写与字段集不一致`})
                }
              })
            }
          }
          if (linkbtn && linkbtn === cell.uuid) {
            linkbtn = ''
          }
        } else if (cell.datatype === 'dynamic' && cell.field && !columns.includes(cell.field)) {
          card.errors.push({ level: 1, detail: `卡片中动态字段“${cell.field}”无效`})
        }
      })
      if (linkbtn) {
        card.errors.push({ level: 1, detail: `第${i + 1}张卡片中绑定按钮已删除`})
      }
    })
    component.width = component.wrap.width
    component.name = component.wrap.name
    this.setState({
      card: card
    })
    this.props.updateConfig(component)
    this.props.updateConfig(card)
  }
  /**
@@ -197,9 +255,7 @@
      return item
    })
    this.setState({card})
    this.props.updateConfig(card)
    this.updateComponent(card)
  }
  /**
@@ -215,12 +271,11 @@
      onOk() {
        card.subcards = card.subcards.filter(item => item.uuid !== cell.uuid)
        if (card.btnlog) {
          card.btnlog = card.btnlog.filter(c => c.$parentId !== cell.uuid)
        }
        // if (card.btnlog) {
        //   card.btnlog = card.btnlog.filter(c => c.$parentId !== cell.uuid)
        // }
        _this.setState({card})
        _this.props.updateConfig(card)
        _this.updateComponent(card)
        if (appType === 'mob') return
@@ -253,11 +308,7 @@
    let _card = {...card, style}
    this.setState({
      card: _card
    })
    this.props.updateConfig(_card)
    this.updateComponent(_card)
  }
  addCard = (copy) => {
@@ -287,9 +338,8 @@
    }
    card.subcards.push(newcard)
    this.setState({card})
    this.props.updateConfig(card)
    this.updateComponent(card)
  }
  addSearch = (copy) => {
@@ -317,52 +367,50 @@
    MKEmitter.emit('addSearch', card.uuid, newcard)
  }
  handleLog = (type, logs, item) => {
    let card = fromJS(this.state.card).toJS()
  // handleLog = (type, logs, item) => {
  //   let card = fromJS(this.state.card).toJS()
    if (type === 'revert') {
      let done = false
      if (item.$parentId) {
        card.subcards.forEach(col => {
          if (item.$parentId === col.uuid) {
            if (item.$side !== 'back') {
              col.elements = col.elements ? [...col.elements, item] : [item]
            } else {
              col.backElements = col.backElements ? [...col.backElements, item] : [item]
            }
            done = true
          }
        })
      }
  //   if (type === 'revert') {
  //     let done = false
  //     if (item.$parentId) {
  //       card.subcards.forEach(col => {
  //         if (item.$parentId === col.uuid) {
  //           if (item.$side !== 'back') {
  //             col.elements = col.elements ? [...col.elements, item] : [item]
  //           } else {
  //             col.backElements = col.backElements ? [...col.backElements, item] : [item]
  //           }
  //           done = true
  //         }
  //       })
  //     }
      card.btnlog = logs
  //     card.btnlog = logs
      this.setState({ card })
      this.props.updateConfig(card)
      if (!done) {
        notification.warning({
          top: 92,
          message: '附属卡片已删除!',
          duration: 2
        })
      } else {
        notification.success({
          top: 92,
          message: '恢复成功!',
          duration: 2
        })
      }
    } else {
      card.btnlog = logs
      this.setState({ card })
      this.props.updateConfig(card)
      notification.success({
        top: 92,
        message: '清除成功!',
        duration: 2
      })
    }
  }
  //     this.updateComponent(card)
  //     if (!done) {
  //       notification.warning({
  //         top: 92,
  //         message: '附属卡片已删除!',
  //         duration: 2
  //       })
  //     } else {
  //       notification.success({
  //         top: 92,
  //         message: '恢复成功!',
  //         duration: 2
  //       })
  //     }
  //   } else {
  //     card.btnlog = logs
  //     this.updateComponent(card)
  //     notification.success({
  //       top: 92,
  //       message: '清除成功!',
  //       duration: 2
  //     })
  //   }
  // }
  move = (item, direction) => {
    let card = fromJS(this.state.card).toJS()
@@ -380,8 +428,7 @@
    card.subcards.splice(hoverIndex, 0, ...card.subcards.splice(dragIndex, 1))
    this.setState({card})
    this.props.updateConfig(card)
    this.updateComponent(card)
  }
  getWrapForms = () => {
@@ -550,7 +597,7 @@
            <CopyComponent type="tablecard" card={card}/>
            <PasteComponent options={['cardcell', 'search', 'form']} updateConfig={this.pasteComponent} />
            <FontColorsOutlined className="style" title="调整样式" onClick={this.changeStyle}/>
            <LogComponent btnlog={card.btnlog || []} handlelog={this.handleLog} />
            {/* <LogComponent btnlog={card.btnlog || []} handlelog={this.handleLog} /> */}
            <UserComponent config={card}/>
            <DeleteOutlined className="close" title="删除组件" onClick={() => this.props.deletecomponent(card.uuid)} />
            {card.wrap.datatype !== 'static' ? <SettingComponent config={card} updateConfig={this.updateComponent} /> : null}
@@ -564,7 +611,20 @@
        </div>
        {card.setting.laypage === 'true' && card.wrap.pagestyle !== 'slide' && appType !== 'mob' ? <Pagination size="small" total={50} /> : null}
        {card.setting.laypage === 'true' && card.wrap.pagestyle !== 'slide' && appType === 'mob' ? <MobPagination /> : null}
        <div className="component-name"><div className="center">{card.name}</div></div>
        <div className="component-name">
          <div className="center">
            <div className="title">{card.name}</div>
            <div className="content">
              {card.errors && card.errors.map((err, index) => {
                if (err.level === 0) {
                  return <span key={index} className="error">{err.detail}</span>
                } else {
                  return <span key={index} className="waring">{err.detail};</span>
                }
              })}
            </div>
          </div>
        </div>
      </div>
    )
  }
src/menu/components/carousel/data-card/index.jsx
@@ -1,7 +1,7 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import { is, fromJS } from 'immutable'
import { Popover, Modal, notification } from 'antd'
import { Popover, Modal } from 'antd'
import { EditOutlined, ToolOutlined, DeleteOutlined, FontColorsOutlined } from '@ant-design/icons'
import asyncComponent from '@/utils/asyncComponent'
@@ -15,7 +15,7 @@
const SettingComponent = asyncIconComponent(() => import('@/menu/datasource'))
const NormalForm = asyncIconComponent(() => import('@/components/normalform'))
const CardSimpleComponent = asyncComponent(() => import('@/menu/components/card/cardsimplecomponent'))
const LogComponent = asyncIconComponent(() => import('@/menu/components/share/logcomponent'))
// const LogComponent = asyncIconComponent(() => import('@/menu/components/share/logcomponent'))
const CopyComponent = asyncIconComponent(() => import('@/menu/components/share/copycomponent'))
const UserComponent = asyncIconComponent(() => import('@/menu/components/share/usercomponent'))
@@ -87,10 +87,7 @@
        })
      }
      this.setState({
        card: _card
      })
      this.props.updateConfig(_card)
      this.updateComponent(_card)
    } else {
      this.setState({
        card: fromJS(card).toJS()
@@ -100,7 +97,7 @@
  componentDidMount () {
    MKEmitter.addListener('submitStyle', this.getStyle)
    MKEmitter.addListener('logButton', this.logButton)
    // MKEmitter.addListener('logButton', this.logButton)
  }
  shouldComponentUpdate (nextProps, nextState) {
@@ -115,35 +112,84 @@
      return
    }
    MKEmitter.removeListener('submitStyle', this.getStyle)
    MKEmitter.removeListener('logButton', this.logButton)
    // MKEmitter.removeListener('logButton', this.logButton)
  }
  logButton = (id, item) => {
    const { card } = this.state
  // logButton = (id, item) => {
  //   const { card } = this.state
    if (id !== card.uuid) return
  //   if (id !== card.uuid) return
    let btnlog = card.btnlog || []
    btnlog.push(item)
  //   let btnlog = card.btnlog || []
  //   btnlog.push(item)
    this.setState({
      card: {...card, btnlog}
    })
    this.props.updateConfig({...card, btnlog})
  }
  //   this.updateComponent({...card, btnlog})
  // }
  
  /**
   * @description 卡片行外层信息更新(数据源,样式等)
   */
  updateComponent = (component) => {
    this.setState({
      card: component
  updateComponent = (card) => {
    card.width = card.wrap.width
    card.name = card.wrap.name
    card.btnlog = []
    if (window.GLOB.styling && card.errors) { // 样式修改时不做筛查
      this.setState({
        card: card
      })
      this.props.updateConfig(card)
      return
    }
    card.errors = []
    if (card.setting.interType === 'system' && card.setting.execute !== 'false' && !card.setting.dataresource) {
      card.errors.push({ level: 0, detail: '未设置数据源!'})
    } else if (card.setting.interType === 'system' && card.setting.execute === 'false' && card.scripts.filter(script => script.status !== 'false').length === 0) {
      card.errors.push({ level: 0, detail: '数据源中无可用脚本!'})
    } else if (!card.setting.primaryKey) {
      card.errors.push({ level: 0, detail: '未设置主键!'})
    } else if (!card.setting.supModule) {
      card.errors.push({ level: 0, detail: '未设置上级组件!'})
    }
    let supModule = card.setting.supModule ? card.setting.supModule[card.setting.supModule.length - 1] || '' : ''
    if (supModule === 'empty') {
      supModule = ''
    }
    let columns = card.columns.map(c => c.field)
    let lowcols = card.columns.map(c => c.field.toLowerCase())
    card.subcards.forEach((item, i) => {
      item.elements.forEach(cell => {
        if (cell.eleType === 'button') {
          if (cell.OpenType === 'pop' || (cell.OpenType === 'funcbutton' && cell.execMode === 'pop')) {
            if (!cell.modal || cell.modal.fields.length === 0) {
              card.errors.push({ level: 1, detail: `按钮“${cell.label}”中表单尚未添加`})
            } else {
              cell.modal.fields.forEach(m => {
                if (m.type === 'linkMain' && !supModule) {
                  card.errors.push({ level: 1, detail: `按钮“${cell.label}”中关联主表表单“${m.label}”无效`})
                } else if (m.field && !columns.includes(m.field) && lowcols.includes(m.field.toLowerCase())) {
                  card.errors.push({ level: 1, detail: `按钮“${cell.label}”中表单“${m.label}”大小写与字段集不一致`})
                }
              })
            }
          }
        } else if (cell.datatype === 'dynamic' && cell.field && !columns.includes(cell.field)) {
          card.errors.push({ level: 1, detail: `卡片中动态字段“${cell.field}”无效`})
        }
      })
    })
    component.width = component.wrap.width
    component.name = component.wrap.name
    this.setState({
      card: card
    })
    this.props.updateConfig(component)
    this.props.updateConfig(card)
  }
  /**
@@ -157,9 +203,7 @@
      return item
    })
    this.setState({card})
    this.props.updateConfig(card)
    this.updateComponent(card)
  }
  /**
@@ -175,12 +219,11 @@
      onOk() {
        card.subcards = card.subcards.filter(item => item.uuid !== cell.uuid)
        if (card.btnlog) {
          card.btnlog = card.btnlog.filter(c => c.$parentId !== cell.uuid)
        }
        // if (card.btnlog) {
        //   card.btnlog = card.btnlog.filter(c => c.$parentId !== cell.uuid)
        // }
        _this.setState({card})
        _this.props.updateConfig(card)
        _this.updateComponent(card)
        if (appType === 'mob') return
@@ -213,44 +256,38 @@
    let _card = {...card, style}
    this.setState({
      card: _card
    })
    this.props.updateConfig(_card)
    this.updateComponent(_card)
  }
  handleLog = (type, logs, item) => {
    let card = fromJS(this.state.card).toJS()
  // handleLog = (type, logs, item) => {
  //   let card = fromJS(this.state.card).toJS()
    if (type === 'revert') {
      card.subcards.forEach(col => {
        col.elements = [...col.elements, item]
        if (item.$parentId === col.uuid) {
          col.elements = [...col.elements, item]
        }
      })
  //   if (type === 'revert') {
  //     card.subcards.forEach(col => {
  //       col.elements = [...col.elements, item]
  //       if (item.$parentId === col.uuid) {
  //         col.elements = [...col.elements, item]
  //       }
  //     })
      card.btnlog = logs
  //     card.btnlog = logs
      this.setState({ card })
      this.props.updateConfig(card)
      notification.success({
        top: 92,
        message: '恢复成功!',
        duration: 2
      })
    } else {
      card.btnlog = logs
      this.setState({ card })
      this.props.updateConfig(card)
      notification.success({
        top: 92,
        message: '清除成功!',
        duration: 2
      })
    }
  }
  //     this.updateComponent(card)
  //     notification.success({
  //       top: 92,
  //       message: '恢复成功!',
  //       duration: 2
  //     })
  //   } else {
  //     card.btnlog = logs
  //     this.updateComponent(card)
  //     notification.success({
  //       top: 92,
  //       message: '清除成功!',
  //       duration: 2
  //     })
  //   }
  // }
  getWrapForms = () => {
    const { card } = this.state
@@ -282,7 +319,7 @@
            </NormalForm>
            <CopyComponent type="datacard" card={card}/>
            <FontColorsOutlined className="style" title="调整样式" onClick={this.changeStyle}/>
            <LogComponent btnlog={card.btnlog || []} handlelog={this.handleLog}/>
            {/* <LogComponent btnlog={card.btnlog || []} handlelog={this.handleLog}/> */}
            <UserComponent config={card}/>
            <DeleteOutlined className="close" title="删除组件" onClick={() => this.props.deletecomponent(card.uuid)}/>
            <SettingComponent config={card} updateConfig={this.updateComponent}/>
@@ -291,7 +328,20 @@
          <ToolOutlined/>
        </Popover>
        <CardSimpleComponent cards={card} card={card.subcards[0]} updateElement={this.updateCard} deleteElement={this.deleteCard}/>
        <div className="component-name"><div className="center">{card.name}</div></div>
        <div className="component-name">
          <div className="center">
            <div className="title">{card.name}</div>
            <div className="content">
              {card.errors && card.errors.map((err, index) => {
                if (err.level === 0) {
                  return <span key={index} className="error">{err.detail}</span>
                } else {
                  return <span key={index} className="waring">{err.detail};</span>
                }
              })}
            </div>
          </div>
        </div>
      </div>
    )
  }
src/menu/components/carousel/prop-card/index.jsx
@@ -1,7 +1,7 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import { is, fromJS } from 'immutable'
import { Popover, Modal, notification, Carousel } from 'antd'
import { Popover, Modal, Carousel } from 'antd'
import { PlusOutlined, SettingOutlined, EditOutlined, ToolOutlined, DeleteOutlined, FontColorsOutlined } from '@ant-design/icons'
import asyncComponent from '@/utils/asyncComponent'
@@ -17,7 +17,7 @@
const CardSimpleComponent = asyncComponent(() => import('@/menu/components/card/cardsimplecomponent'))
const CopyComponent = asyncIconComponent(() => import('@/menu/components/share/copycomponent'))
const PasteComponent = asyncIconComponent(() => import('@/menu/components/share/pastecomponent'))
const LogComponent = asyncIconComponent(() => import('@/menu/components/share/logcomponent'))
// const LogComponent = asyncIconComponent(() => import('@/menu/components/share/logcomponent'))
const UserComponent = asyncIconComponent(() => import('@/menu/components/share/usercomponent'))
const { confirm } = Modal
@@ -85,10 +85,8 @@
          return scard
        })
      }
      this.setState({
        card: _card
      })
      this.props.updateConfig(_card)
      this.updateComponent(_card)
    } else {
      this.setState({
        card: fromJS(card).toJS()
@@ -98,7 +96,7 @@
  componentDidMount () {
    MKEmitter.addListener('submitStyle', this.getStyle)
    MKEmitter.addListener('logButton', this.logButton)
    // MKEmitter.addListener('logButton', this.logButton)
    MKEmitter.addListener('submitComponentStyle', this.updateComponentStyle)
  }
@@ -114,7 +112,7 @@
      return
    }
    MKEmitter.removeListener('submitStyle', this.getStyle)
    MKEmitter.removeListener('logButton', this.logButton)
    // MKEmitter.removeListener('logButton', this.logButton)
    MKEmitter.removeListener('submitComponentStyle', this.updateComponentStyle)
  }
@@ -135,32 +133,106 @@
    })
  }
  logButton = (id, item) => {
    const { card } = this.state
  // logButton = (id, item) => {
  //   const { card } = this.state
    if (id !== card.uuid) return
  //   if (id !== card.uuid) return
    let btnlog = card.btnlog || []
    btnlog.push(item)
  //   let btnlog = card.btnlog || []
  //   btnlog.push(item)
    this.setState({
      card: {...card, btnlog}
    })
    this.props.updateConfig({...card, btnlog})
  }
  //   this.updateComponent({...card, btnlog})
  // }
  /**
   * @description 卡片行外层信息更新(数据源,样式等)
   */
  updateComponent = (component) => {
  updateComponent = (card) => {
    card.width = card.wrap.width
    card.name = card.wrap.name
    card.btnlog = []
    if (window.GLOB.styling && card.errors) { // 样式修改时不做筛查
      this.setState({
        card: card
      })
      this.props.updateConfig(card)
      return
    }
    card.errors = []
    if (card.subcards.length === 0) {
      card.errors.push({ level: 0, detail: '卡片不可为空!'})
    }
    if (card.wrap.datatype === 'static') {
      card.subcards.forEach(item => {
        item.elements.forEach(cell => {
          if (cell.eleType === 'button') {
            if (cell.OpenType === 'pop' || (cell.OpenType === 'funcbutton' && cell.execMode === 'pop')) {
              if (!cell.modal || cell.modal.fields.length === 0) {
                card.errors.push({ level: 1, detail: `按钮“${cell.label}”中表单尚未添加`})
              } else {
                cell.modal.fields.forEach(m => {
                  if (m.type === 'linkMain') {
                    card.errors.push({ level: 1, detail: `按钮“${cell.label}”中关联主表表单“${m.label}”无效`})
                  }
                })
              }
            }
          } else if (cell.datatype === 'dynamic' && cell.field) {
            card.errors.push({ level: 1, detail: `卡片中动态字段“${cell.field}”无效`})
          }
        })
      })
    } else {
      if (card.setting.interType === 'system' && card.setting.execute !== 'false' && !card.setting.dataresource) {
        card.errors.push({ level: 0, detail: '未设置数据源!'})
      } else if (card.setting.interType === 'system' && card.setting.execute === 'false' && card.scripts.filter(script => script.status !== 'false').length === 0) {
        card.errors.push({ level: 0, detail: '数据源中无可用脚本!'})
      } else if (!card.setting.primaryKey) {
        card.errors.push({ level: 0, detail: '未设置主键!'})
      } else if (!card.setting.supModule) {
        card.errors.push({ level: 0, detail: '未设置上级组件!'})
      }
      let supModule = card.setting.supModule ? card.setting.supModule[card.setting.supModule.length - 1] || '' : ''
      if (supModule === 'empty') {
        supModule = ''
      }
      let columns = card.columns.map(c => c.field)
      let lowcols = card.columns.map(c => c.field.toLowerCase())
      card.subcards.forEach((item, i) => {
        item.elements.forEach(cell => {
          if (cell.eleType === 'button') {
            if (cell.OpenType === 'pop' || (cell.OpenType === 'funcbutton' && cell.execMode === 'pop')) {
              if (!cell.modal || cell.modal.fields.length === 0) {
                card.errors.push({ level: 1, detail: `按钮“${cell.label}”中表单尚未添加`})
              } else {
                cell.modal.fields.forEach(m => {
                  if (m.type === 'linkMain' && !supModule) {
                    card.errors.push({ level: 1, detail: `按钮“${cell.label}”中关联主表表单“${m.label}”无效`})
                  } else if (m.field && !columns.includes(m.field) && lowcols.includes(m.field.toLowerCase())) {
                    card.errors.push({ level: 1, detail: `按钮“${cell.label}”中表单“${m.label}”大小写与字段集不一致`})
                  }
                })
              }
            }
          } else if (cell.datatype === 'dynamic' && cell.field && !columns.includes(cell.field)) {
            card.errors.push({ level: 1, detail: `卡片中动态字段“${cell.field}”无效`})
          }
        })
      })
    }
    this.setState({
      card: component
      card: card
    })
    component.width = component.wrap.width
    component.name = component.wrap.name
    this.props.updateConfig(component)
    this.props.updateConfig(card)
  }
  /**
@@ -174,9 +246,7 @@
      return item
    })
    this.setState({card})
    this.props.updateConfig(card)
    this.updateComponent(card)
  }
  /**
@@ -192,12 +262,11 @@
      onOk() {
        card.subcards = card.subcards.filter(item => item.uuid !== cell.uuid)
        if (card.btnlog) {
          card.btnlog = card.btnlog.filter(c => c.$parentId !== cell.uuid)
        }
        // if (card.btnlog) {
        //   card.btnlog = card.btnlog.filter(c => c.$parentId !== cell.uuid)
        // }
        _this.setState({card})
        _this.props.updateConfig(card)
        _this.updateComponent(card)
        if (appType === 'mob') return
@@ -229,12 +298,8 @@
    if (comIds.length !== 1 || comIds[0] !== card.uuid) return
    let _card = {...card, style}
    this.setState({
      card: _card
    })
    
    this.props.updateConfig(_card)
    this.updateComponent(_card)
  }
  addCard = () => {
@@ -257,55 +322,52 @@
    }
    card.subcards.push(newcard)
    this.setState({card})
    this.props.updateConfig(card)
    this.updateComponent(card)
  }
  handleLog = (type, logs, item) => {
    let card = fromJS(this.state.card).toJS()
  // handleLog = (type, logs, item) => {
  //   let card = fromJS(this.state.card).toJS()
    if (type === 'revert') {
      let done = false
      if (item.$parentId) {
        card.subcards.forEach(col => {
          if (item.$parentId === col.uuid) {
            col.elements = [...col.elements, item]
            done = true
          }
        })
      }
  //   if (type === 'revert') {
  //     let done = false
  //     if (item.$parentId) {
  //       card.subcards.forEach(col => {
  //         if (item.$parentId === col.uuid) {
  //           col.elements = [...col.elements, item]
  //           done = true
  //         }
  //       })
  //     }
      card.btnlog = logs
  //     card.btnlog = logs
      this.setState({ card: {...card, subcards: []} }, () => {
        this.setState({ card })
        this.props.updateConfig(card)
      })
      if (!done) {
        notification.warning({
          top: 92,
          message: '附属卡片已删除!',
          duration: 2
        })
      } else {
        notification.success({
          top: 92,
          message: '恢复成功!',
          duration: 2
        })
      }
    } else {
      card.btnlog = logs
      this.setState({ card })
      this.props.updateConfig(card)
      notification.success({
        top: 92,
        message: '清除成功!',
        duration: 2
      })
    }
  }
  //     this.setState({ card: {...card, subcards: []} }, () => {
  //       this.updateComponent(card)
  //     })
  //     if (!done) {
  //       notification.warning({
  //         top: 92,
  //         message: '附属卡片已删除!',
  //         duration: 2
  //       })
  //     } else {
  //       notification.success({
  //         top: 92,
  //         message: '恢复成功!',
  //         duration: 2
  //       })
  //     }
  //   } else {
  //     card.btnlog = logs
  //     this.updateComponent(card)
  //     notification.success({
  //       top: 92,
  //       message: '清除成功!',
  //       duration: 2
  //     })
  //   }
  // }
  move = (item, direction) => {
    let card = fromJS(this.state.card).toJS()
@@ -324,9 +386,8 @@
    card.subcards.splice(hoverIndex, 0, ...card.subcards.splice(dragIndex, 1))
    this.setState({card: {...card, subcards: []}}, () => {
      this.setState({card})
      this.updateComponent(card)
    })
    this.props.updateConfig(card)
  }
  getWrapForms = () => {
@@ -361,7 +422,7 @@
            <CopyComponent type="propcard" card={card}/>
            <PasteComponent config={card} options={['cardcell']} updateConfig={this.updateComponent} />
            <FontColorsOutlined className="style" title="调整样式" onClick={this.changeStyle}/>
            <LogComponent btnlog={card.btnlog || []} handlelog={this.handleLog} />
            {/* <LogComponent btnlog={card.btnlog || []} handlelog={this.handleLog} /> */}
            <UserComponent config={card}/>
            <DeleteOutlined className="close" title="删除组件" onClick={() => this.props.deletecomponent(card.uuid)} />
            {card.wrap.datatype !== 'static' ? <SettingComponent config={card} updateConfig={this.updateComponent} /> : null}
@@ -373,7 +434,20 @@
        {card.subcards.length > 0 ? <Carousel dotPosition={card.wrap.dotPosition || 'bottom'} effect={card.wrap.effect || 'scrollx'}>
          {card.subcards.map((subcard) => (<CardSimpleComponent key={subcard.uuid} cards={card} card={subcard} move={this.move} updateElement={this.updateCard} deleteElement={this.deleteCard}/>))}
        </Carousel> : null}
        <div className="component-name"><div className="center">{card.name}</div></div>
        <div className="component-name">
          <div className="center">
            <div className="title">{card.name}</div>
            <div className="content">
              {card.errors && card.errors.map((err, index) => {
                if (err.level === 0) {
                  return <span key={index} className="error">{err.detail}</span>
                } else {
                  return <span key={index} className="waring">{err.detail};</span>
                }
              })}
            </div>
          </div>
        </div>
      </div>
    )
  }
src/menu/components/chart/antv-bar/index.jsx
@@ -1,7 +1,7 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import { is, fromJS } from 'immutable'
import { Popover, notification } from 'antd'
import { Popover } from 'antd'
import { PlusCircleOutlined, PlusSquareOutlined, ToolOutlined, DeleteOutlined, FontColorsOutlined } from '@ant-design/icons'
import { Chart } from '@antv/g2'
import DataSet from '@antv/data-set'
@@ -18,7 +18,7 @@
const SettingComponent = asyncIconComponent(() => import('@/menu/datasource'))
const ChartCompileForm = asyncIconComponent(() => import('./chartcompile'))
const LogComponent = asyncIconComponent(() => import('@/menu/components/share/logcomponent'))
// const LogComponent = asyncIconComponent(() => import('@/menu/components/share/logcomponent'))
const CopyComponent = asyncIconComponent(() => import('@/menu/components/share/copycomponent'))
const PasteComponent = asyncIconComponent(() => import('@/menu/components/share/pastecomponent'))
const NormalHeader = asyncComponent(() => import('@/menu/components/share/normalheader'))
@@ -114,10 +114,8 @@
          return col
        })
      }
      this.setState({
        card: _card
      })
      this.props.updateConfig(_card)
      this.updateComponent(_card, true)
    } else {
      this.setState({
        card: fromJS(card).toJS()
@@ -1212,26 +1210,65 @@
    }
  }
  updateComponent = (component) => {
    const card = fromJS(this.state.card).toJS()
    if (!is(fromJS(component.plot), fromJS(card.plot)) || !is(fromJS(component.style), fromJS(card.style)) || !is(fromJS(component.search), fromJS(card.search))) {
      let _element = document.getElementById(card.uuid + 'canvas')
      if (_element) {
        _element.innerHTML = ''
  updateComponent = (card, init) => {
    if (!init) {
      if (!is(fromJS({plot: card.plot, style: card.style, search: card.search}), fromJS({plot: this.state.card.plot, style: this.state.card.style, search: this.state.card.search}))) {
        let _element = document.getElementById(this.state.card.uuid + 'canvas')
        if (_element) {
          _element.innerHTML = ''
        }
        this.$timer && clearTimeout(this.$timer)
        this.$timer = setTimeout(() => {
          this.viewrender()
        }, 150)
      }
      this.$timer && clearTimeout(this.$timer)
      this.$timer = setTimeout(() => {
        this.viewrender()
      }, 150)
    }
    component.width = component.plot.width
    component.name = component.plot.name
    card.width = card.plot.width
    card.name = card.plot.name
    card.btnlog = []
    card.errors = []
    if (card.setting.interType === 'system' && card.setting.execute !== 'false' && !card.setting.dataresource) {
      card.errors.push({ level: 0, detail: '未设置数据源!'})
    } else if (card.setting.interType === 'system' && card.setting.execute === 'false' && card.scripts.filter(script => script.status !== 'false').length === 0) {
      card.errors.push({ level: 0, detail: '数据源中无可用脚本!'})
    } else if (!card.setting.primaryKey) {
      card.errors.push({ level: 0, detail: '未设置主键!'})
    } else if (!card.setting.supModule) {
      card.errors.push({ level: 0, detail: '未设置上级组件!'})
    }
    let columns = card.columns.map(c => c.field)
    if (!card.plot.Xaxis) {
      card.errors.push({ level: 0, detail: '坐标轴尚未设置!'})
    } else if (card.plot.datatype === 'query') {
      if (!columns.includes(card.plot.Xaxis)) {
        card.errors.push({ level: 1, detail: 'X轴在字段集中不存在'})
      }
      if (card.plot.Yaxis) {
        card.plot.Yaxis.forEach(m => {
          if (!columns.includes(m)) {
            card.errors.push({ level: 1, detail: `Y轴中字段“${m}”已失效`})
          }
        })
      }
    } else if (card.plot.datatype === 'statistics') {
      if (!columns.includes(card.plot.Xaxis)) {
        card.errors.push({ level: 1, detail: 'X轴在字段集中不存在'})
      }
      if (!columns.includes(card.plot.InfoType)) {
        card.errors.push({ level: 1, detail: '图表中统计类型字段已失效'})
      }
      if (!columns.includes(card.plot.InfoValue)) {
        card.errors.push({ level: 1, detail: '图表中统计值字段已失效'})
      }
    }
    this.setState({
      card: component
      card: card
    })
    this.props.updateConfig(component)
    this.props.updateConfig(card)
  }
  addSearch = () => {
@@ -1307,31 +1344,29 @@
    this.updateComponent(_card)
  }
  handleLog = (type, logs, item) => {
    let card = fromJS(this.state.card).toJS()
  // handleLog = (type, logs, item) => {
  //   let card = fromJS(this.state.card).toJS()
    if (type === 'revert') {
      card.action = card.action ? [...card.action, item] : [item]
      card.btnlog = logs
  //   if (type === 'revert') {
  //     card.action = card.action ? [...card.action, item] : [item]
  //     card.btnlog = logs
      this.setState({ card })
      this.props.updateConfig(card)
      notification.success({
        top: 92,
        message: '恢复成功!',
        duration: 2
      })
    } else {
      card.btnlog = logs
      this.setState({ card })
      this.props.updateConfig(card)
      notification.success({
        top: 92,
        message: '清除成功!',
        duration: 2
      })
    }
  }
  //     this.updateComponent(card)
  //     notification.success({
  //       top: 92,
  //       message: '恢复成功!',
  //       duration: 2
  //     })
  //   } else {
  //     card.btnlog = logs
  //     this.updateComponent(card)
  //     notification.success({
  //       top: 92,
  //       message: '清除成功!',
  //       duration: 2
  //     })
  //   }
  // }
  clickComponent = (e) => {
    if (sessionStorage.getItem('style-control') === 'true' || sessionStorage.getItem('style-control') === 'component') {
@@ -1354,7 +1389,7 @@
            <CopyComponent type="line" card={card}/>
            <PasteComponent config={card} options={['action', 'search']} updateConfig={this.updateComponent} />
            <FontColorsOutlined className="style" title="调整样式" onClick={this.changeStyle}/>
            <LogComponent btnlog={card.btnlog || []} handlelog={this.handleLog} />
            {/* <LogComponent btnlog={card.btnlog || []} handlelog={this.handleLog} /> */}
            <ClockComponent config={card} updateConfig={this.updateComponent}/>
            <UserComponent config={card}/>
            <DeleteOutlined className="close" title="delete" onClick={() => this.props.deletecomponent(card.uuid)} />
@@ -1370,7 +1405,20 @@
          config={card}
          updateaction={this.updateComponent}
        /> : null}
        <div className="component-name"><div className="center">{card.name}</div></div>
        <div className="component-name">
          <div className="center">
            <div className="title">{card.name}</div>
            <div className="content">
              {card.errors && card.errors.map((err, index) => {
                if (err.level === 0) {
                  return <span key={index} className="error">{err.detail}</span>
                } else {
                  return <span key={index} className="waring">{err.detail};</span>
                }
              })}
            </div>
          </div>
        </div>
      </div>
    )
  }
src/menu/components/chart/antv-dashboard/index.jsx
@@ -67,12 +67,13 @@
  state = {
    dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS,
    card: null,
    ismob: sessionStorage.getItem('appType') === 'mob',
    appType: sessionStorage.getItem('appType'),
    eventListener: null
  }
  UNSAFE_componentWillMount () {
    const { card, ismob } = this.props
    const { card } = this.props
    const { appType } = this.state
    if (card.isNew) {
      let _plot = null
@@ -105,7 +106,7 @@
        }
      }
      if (ismob) {
      if (appType === 'mob') {
        _plot.width = 24
      }
@@ -132,7 +133,6 @@
        search: [],
        action: [],
        plot: _plot,
        btnlog: [],
      }
      if (card.config) {
@@ -148,10 +148,7 @@
        _card.scripts = config.scripts
      }
      this.props.updateConfig(_card)
      this.setState({
        card: _card
      })
      this.updateComponent(_card, true)
    } else {
      this.setState({
        card: fromJS(card).toJS()
@@ -467,27 +464,46 @@
    chart.render()
  }
  updateComponent = (component) => {
    const card = fromJS(this.state.card).toJS()
    if (!is(fromJS(component.plot), fromJS(card.plot)) || !is(fromJS(component.style), fromJS(card.style)) || !is(fromJS(component.search), fromJS(card.search))) {
      let _element = document.getElementById(card.uuid + 'dashboard')
      if (_element) {
        _element.innerHTML = ''
  updateComponent = (card, init) => {
    if (!init) {
      if (!is(fromJS({plot: card.plot, style: card.style}), fromJS({plot: this.state.card.plot, style: this.state.card.style}))) {
        let _element = document.getElementById(this.state.card.uuid + 'dashboard')
        if (_element) {
          _element.innerHTML = ''
        }
        this.$timer && clearTimeout(this.$timer)
        this.$timer = setTimeout(() => {
          this.viewrender()
        }, 150)
      }
      this.$timer && clearTimeout(this.$timer)
      this.$timer = setTimeout(() => {
        this.viewrender()
      }, 150)
    }
    component.width = component.plot.width
    component.name = component.plot.name
    card.width = card.plot.width
    card.name = card.plot.name
    card.errors = []
    if (card.setting.interType === 'system' && card.setting.execute !== 'false' && !card.setting.dataresource) {
      card.errors.push({ level: 0, detail: '未设置数据源!'})
    } else if (card.setting.interType === 'system' && card.setting.execute === 'false' && card.scripts.filter(script => script.status !== 'false').length === 0) {
      card.errors.push({ level: 0, detail: '数据源中无可用脚本!'})
    } else if (!card.setting.primaryKey) {
      card.errors.push({ level: 0, detail: '未设置主键!'})
    } else if (!card.setting.supModule) {
      card.errors.push({ level: 0, detail: '未设置上级组件!'})
    }
    let columns = card.columns.map(c => c.field)
    if (!card.plot.valueField) {
      card.errors.push({ level: 0, detail: '显示值尚未设置!'})
    } else if (!columns.includes(card.plot.valueField)) {
      card.errors.push({ level: 1, detail: '显示值在字段集中不存在'})
    }
    
    this.setState({
      card: component
      card: card
    })
    this.props.updateConfig(component)
    this.props.updateConfig(card)
  }
  changeStyle = () => {
@@ -534,7 +550,20 @@
        </Popover>
        <NormalHeader hideSearch="true" config={card} updateComponent={this.updateComponent}/>
        <div className="canvas" id={card.uuid + 'dashboard'} ref={ref => this.wrap = ref}></div>
        <div className="component-name"><div className="center">{card.name}</div></div>
        <div className="component-name">
          <div className="center">
            <div className="title">{card.name}</div>
            <div className="content">
              {card.errors && card.errors.map((err, index) => {
                if (err.level === 0) {
                  return <span key={index} className="error">{err.detail}</span>
                } else {
                  return <span key={index} className="waring">{err.detail};</span>
                }
              })}
            </div>
          </div>
        </div>
      </div>
    )
  }
src/menu/components/chart/antv-pie/index.jsx
@@ -32,12 +32,13 @@
  state = {
    dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS,
    card: null,
    ismob: sessionStorage.getItem('appType') === 'mob',
    appType: sessionStorage.getItem('appType'),
    eventListener: null
  }
  UNSAFE_componentWillMount () {
    const { card, ismob } = this.props
    const { card } = this.props
    const { appType } = this.state
    if (card.isNew) {
      let _plot = {
@@ -48,7 +49,7 @@
        name: card.name
      }
      if (ismob) {
      if (appType === 'mob') {
        _plot.width = 24
      }
@@ -97,16 +98,15 @@
        _card.columns = config.columns
        _card.scripts = config.scripts
        _card.search = config.search.map(col => {
          col.uuid = Utils.getuuid()
          return col
        })
        if (appType !== 'mob') {
          _card.search = config.search.map(col => {
            col.uuid = Utils.getuuid()
            return col
          })
        }
      }
      this.props.updateConfig(_card)
      this.setState({
        card: _card
      })
      this.updateComponent(_card, true)
    } else {
      this.setState({
        card: fromJS(card).toJS()
@@ -599,27 +599,50 @@
    chart.render()
  }
  updateComponent = (component) => {
    const card = fromJS(this.state.card).toJS()
    if (!is(fromJS(component.plot), fromJS(card.plot)) || !is(fromJS(component.style), fromJS(card.style)) || !is(fromJS(component.search), fromJS(card.search))) {
      let _element = document.getElementById(card.uuid + 'canvas')
      if (_element) {
        _element.innerHTML = ''
  updateComponent = (card, init) => {
    if (!init) {
      if (!is(fromJS({plot: card.plot, style: card.style, search: card.search}), fromJS({plot: this.state.card.plot, style: this.state.card.style, search: this.state.card.search}))) {
        let _element = document.getElementById(card.uuid + 'canvas')
        if (_element) {
          _element.innerHTML = ''
        }
        this.$timer && clearTimeout(this.$timer)
        this.$timer = setTimeout(() => {
          this.viewrender()
        }, 150)
      }
      this.$timer && clearTimeout(this.$timer)
      this.$timer = setTimeout(() => {
        this.viewrender()
      }, 150)
    }
    component.width = component.plot.width
    component.name = component.plot.name
    card.width = card.plot.width
    card.name = card.plot.name
    card.errors = []
    if (card.setting.interType === 'system' && card.setting.execute !== 'false' && !card.setting.dataresource) {
      card.errors.push({ level: 0, detail: '未设置数据源!'})
    } else if (card.setting.interType === 'system' && card.setting.execute === 'false' && card.scripts.filter(script => script.status !== 'false').length === 0) {
      card.errors.push({ level: 0, detail: '数据源中无可用脚本!'})
    } else if (!card.setting.primaryKey) {
      card.errors.push({ level: 0, detail: '未设置主键!'})
    } else if (!card.setting.supModule) {
      card.errors.push({ level: 0, detail: '未设置上级组件!'})
    }
    let columns = card.columns.map(c => c.field)
    if (!card.plot.Xaxis) {
      card.errors.push({ level: 0, detail: '名称字段尚未设置!'})
    } else {
      if (!columns.includes(card.plot.Xaxis)) {
        card.errors.push({ level: 1, detail: '名称字段在字段集中不存在'})
      }
      if (!columns.includes(card.plot.Yaxis)) {
        card.errors.push({ level: 1, detail: '值字段在字段集中不存在'})
      }
    }
    
    this.setState({
      card: component
      card: card
    })
    this.props.updateConfig(component)
    this.props.updateConfig(card)
  }
  addSearch = () => {
@@ -665,14 +688,14 @@
  }
  render() {
    const { card, ismob } = this.state
    const { card, appType } = this.state
    let _style = resetStyle(card.style)
    return (
      <div className="menu-pie-chart-edit-box" style={{..._style, height: card.plot.height || 400}} onClick={this.clickComponent} id={card.uuid}>
        <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={
          <div className="mk-popover-control">
            {!ismob ? <PlusCircleOutlined className="plus" title="添加搜索" onClick={this.addSearch}/> : null}
            {appType !== 'mob' ? <PlusCircleOutlined className="plus" title="添加搜索" onClick={this.addSearch}/> : null}
            <ChartCompileForm config={card} dict={this.state.dict} plotchange={this.updateComponent}/>
            <CopyComponent type="pie" card={card}/>
            <FontColorsOutlined className="style" title="调整样式" onClick={this.changeStyle}/>
@@ -686,7 +709,20 @@
        </Popover>
        <NormalHeader config={card} updateComponent={this.updateComponent}/>
        <div className="canvas" id={card.uuid + 'canvas'} ref={ref => this.wrap = ref}></div>
        <div className="component-name"><div className="center">{card.name}</div></div>
        <div className="component-name">
          <div className="center">
            <div className="title">{card.name}</div>
            <div className="content">
              {card.errors && card.errors.map((err, index) => {
                if (err.level === 0) {
                  return <span key={index} className="error">{err.detail}</span>
                } else {
                  return <span key={index} className="waring">{err.detail};</span>
                }
              })}
            </div>
          </div>
        </div>
      </div>
    )
  }
src/menu/components/chart/antv-scatter/index.jsx
@@ -1,7 +1,7 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import { is, fromJS } from 'immutable'
import { Popover, notification } from 'antd'
import { Popover } from 'antd'
import { ToolOutlined, DeleteOutlined, FontColorsOutlined, PlusCircleOutlined, PlusSquareOutlined } from '@ant-design/icons'
import { Chart } from '@antv/g2'
@@ -16,7 +16,7 @@
const SettingComponent = asyncIconComponent(() => import('@/menu/datasource'))
const ChartCompileForm = asyncIconComponent(() => import('./chartcompile'))
const LogComponent = asyncIconComponent(() => import('@/menu/components/share/logcomponent'))
// const LogComponent = asyncIconComponent(() => import('@/menu/components/share/logcomponent'))
const CopyComponent = asyncIconComponent(() => import('@/menu/components/share/copycomponent'))
const PasteComponent = asyncIconComponent(() => import('@/menu/components/share/pastecomponent'))
const NormalHeader = asyncComponent(() => import('@/menu/components/share/normalheader'))
@@ -102,10 +102,8 @@
          return col
        })
      }
      this.setState({
        card: _card
      })
      this.props.updateConfig(_card)
      this.updateComponent(_card, true)
    } else {
      this.setState({
        card: fromJS(card).toJS()
@@ -249,27 +247,50 @@
    chart.render()
  }
  updateComponent = (component) => {
    const card = fromJS(this.state.card).toJS()
    if (!is(fromJS(component.plot), fromJS(card.plot)) || !is(fromJS(component.style), fromJS(card.style)) || !is(fromJS(component.search), fromJS(card.search))) {
      let _element = document.getElementById(card.uuid + 'canvas')
      if (_element) {
        _element.innerHTML = ''
  updateComponent = (card, init) => {
    if (!init) {
      if (!is(fromJS({plot: card.plot, style: card.style, search: card.search}), fromJS({plot: this.state.card.plot, style: this.state.card.style, search: this.state.card.search}))) {
        let _element = document.getElementById(card.uuid + 'canvas')
        if (_element) {
          _element.innerHTML = ''
        }
        this.$timer && clearTimeout(this.$timer)
        this.$timer = setTimeout(() => {
          this.ponitrender()
        }, 150)
      }
      this.$timer && clearTimeout(this.$timer)
      this.$timer = setTimeout(() => {
        this.ponitrender()
      }, 150)
    }
    component.width = component.plot.width
    component.name = component.plot.name
    card.width = card.plot.width
    card.name = card.plot.name
    card.errors = []
    if (card.setting.interType === 'system' && card.setting.execute !== 'false' && !card.setting.dataresource) {
      card.errors.push({ level: 0, detail: '未设置数据源!'})
    } else if (card.setting.interType === 'system' && card.setting.execute === 'false' && card.scripts.filter(script => script.status !== 'false').length === 0) {
      card.errors.push({ level: 0, detail: '数据源中无可用脚本!'})
    } else if (!card.setting.primaryKey) {
      card.errors.push({ level: 0, detail: '未设置主键!'})
    } else if (!card.setting.supModule) {
      card.errors.push({ level: 0, detail: '未设置上级组件!'})
    }
    let columns = card.columns.map(c => c.field)
    if (!card.plot.Xaxis) {
      card.errors.push({ level: 0, detail: '坐标轴尚未设置!'})
    } else {
      if (!columns.includes(card.plot.Xaxis)) {
        card.errors.push({ level: 1, detail: 'X轴在字段集中不存在'})
      }
      if (!columns.includes(card.plot.Yaxis)) {
        card.errors.push({ level: 1, detail: 'Y轴在字段集中不存在'})
      }
    }
    this.setState({
      card: component
      card: card
    })
    this.props.updateConfig(component)
    this.props.updateConfig(card)
  }
  addSearch = () => {
@@ -345,31 +366,29 @@
    this.updateComponent(_card)
  }
  handleLog = (type, logs, item) => {
    let card = fromJS(this.state.card).toJS()
  // handleLog = (type, logs, item) => {
  //   let card = fromJS(this.state.card).toJS()
    if (type === 'revert') {
      card.action = card.action ? [...card.action, item] : [item]
      card.btnlog = logs
  //   if (type === 'revert') {
  //     card.action = card.action ? [...card.action, item] : [item]
  //     card.btnlog = logs
      this.setState({ card })
      this.props.updateConfig(card)
      notification.success({
        top: 92,
        message: '恢复成功!',
        duration: 2
      })
    } else {
      card.btnlog = logs
      this.setState({ card })
      this.props.updateConfig(card)
      notification.success({
        top: 92,
        message: '清除成功!',
        duration: 2
      })
    }
  }
  //     this.updateComponent(card)
  //     notification.success({
  //       top: 92,
  //       message: '恢复成功!',
  //       duration: 2
  //     })
  //   } else {
  //     card.btnlog = logs
  //     this.updateComponent(card)
  //     notification.success({
  //       top: 92,
  //       message: '清除成功!',
  //       duration: 2
  //     })
  //   }
  // }
  clickComponent = (e) => {
    if (sessionStorage.getItem('style-control') === 'true' || sessionStorage.getItem('style-control') === 'component') {
@@ -392,7 +411,7 @@
            <CopyComponent type="line" card={card}/>
            <PasteComponent config={card} options={['action', 'search']} updateConfig={this.updateComponent}/>
            <FontColorsOutlined className="style" title="调整样式" onClick={this.changeStyle}/>
            <LogComponent btnlog={card.btnlog || []} handlelog={this.handleLog}/>
            {/* <LogComponent btnlog={card.btnlog || []} handlelog={this.handleLog}/> */}
            <ClockComponent config={card} updateConfig={this.updateComponent}/>
            <UserComponent config={card}/>
            <DeleteOutlined className="close" title="delete" onClick={() => this.props.deletecomponent(card.uuid)}/>
@@ -404,7 +423,20 @@
        <NormalHeader config={card} updateComponent={this.updateComponent}/>
        <div className="canvas" id={card.uuid + 'canvas'} ref={ref => this.wrap = ref}></div>
        {appType !== 'mob' ? <ActionComponent type="chart" config={card} updateaction={this.updateComponent}/> : null}
        <div className="component-name"><div className="center">{card.name}</div></div>
        <div className="component-name">
          <div className="center">
            <div className="title">{card.name}</div>
            <div className="content">
              {card.errors && card.errors.map((err, index) => {
                if (err.level === 0) {
                  return <span key={index} className="error">{err.detail}</span>
                } else {
                  return <span key={index} className="waring">{err.detail};</span>
                }
              })}
            </div>
          </div>
        </div>
      </div>
    )
  }
src/menu/components/chart/chart-custom/index.jsx
@@ -90,10 +90,8 @@
          return col
        })
      }
      this.setState({
        card: _card
      })
      this.props.updateConfig(_card)
      this.updateComponent(_card, true)
    } else {
      this.setState({
        card: fromJS(card).toJS()
@@ -176,28 +174,40 @@
    }
  }
  updateComponent = (component) => {
    const card = fromJS(this.state.card).toJS()
    if (!is(fromJS(component.plot), fromJS(card.plot)) || !is(fromJS(component.style), fromJS(card.style)) || !is(fromJS(component.search), fromJS(card.search))) {
      let _element = document.getElementById(card.uuid + 'canvas')
      if (_element) {
        _element.innerHTML = ''
        _element.removeAttribute('_echarts_instance_')
        _element.removeAttribute('style')
  updateComponent = (card, init) => {
    if (!init) {
      if (!is(fromJS({plot: card.plot, style: card.style, search: card.search}), fromJS({plot: this.state.card.plot, style: this.state.card.style, search: this.state.card.search}))) {
        let _element = document.getElementById(card.uuid + 'canvas')
        if (_element) {
          _element.innerHTML = ''
          _element.removeAttribute('_echarts_instance_')
          _element.removeAttribute('style')
        }
        this.$timer && clearTimeout(this.$timer)
        this.$timer = setTimeout(() => {
          this.viewrender()
        }, 150)
      }
      this.$timer && clearTimeout(this.$timer)
      this.$timer = setTimeout(() => {
        this.viewrender()
      }, 150)
    }
    component.width = component.plot.width
    component.name = component.plot.name
    card.width = card.plot.width
    card.name = card.plot.name
    card.errors = []
    if (card.setting.interType === 'system' && card.setting.execute !== 'false' && !card.setting.dataresource) {
      card.errors.push({ level: 0, detail: '未设置数据源!'})
    } else if (card.setting.interType === 'system' && card.setting.execute === 'false' && card.scripts.filter(script => script.status !== 'false').length === 0) {
      card.errors.push({ level: 0, detail: '数据源中无可用脚本!'})
    } else if (!card.setting.primaryKey) {
      card.errors.push({ level: 0, detail: '未设置主键!'})
    } else if (!card.setting.supModule) {
      card.errors.push({ level: 0, detail: '未设置上级组件!'})
    }
    
    this.setState({
      card: component
      card: card
    })
    this.props.updateConfig(component)
    this.props.updateConfig(card)
  }
  addSearch = () => {
@@ -263,7 +273,20 @@
        </Popover>
        <NormalHeader config={card} updateComponent={this.updateComponent}/>
        <div className="canvas" id={card.uuid + 'canvas'} ref={ref => this.wrap = ref}></div>
        <div className="component-name"><div className="center">{card.name}</div></div>
        <div className="component-name">
          <div className="center">
            <div className="title">{card.name}</div>
            <div className="content">
              {card.errors && card.errors.map((err, index) => {
                if (err.level === 0) {
                  return <span key={index} className="error">{err.detail}</span>
                } else {
                  return <span key={index} className="waring">{err.detail};</span>
                }
              })}
            </div>
          </div>
        </div>
      </div>
    )
  }
src/menu/components/code/sandbox/index.jsx
@@ -51,7 +51,7 @@
        name: card.name,
        subtype: card.subtype,
        setting: { interType: 'system' },
        wrap: { name: card.name, width: card.width || 24, encryption: 'true' },
        wrap: { name: card.name, datatype: 'dynamic', width: card.width || 24, encryption: 'true' },
        style: { marginLeft: '8px', marginRight: '8px', marginTop: '8px', marginBottom: '8px' },
        columns: [],
        scripts: [],
@@ -75,10 +75,7 @@
        _card.scripts = config.scripts
      }
      
      this.setState({
        card: _card
      })
      this.props.updateConfig(_card)
      this.updateComponent(_card)
    } else {
      this.setState({
        card: fromJS(card).toJS()
@@ -107,15 +104,29 @@
  /**
   * @description 卡片行外层信息更新(数据源,样式等)
   */
  updateComponent = (component) => {
  updateComponent = (card) => {
    card.width = card.wrap.width
    card.name = card.wrap.name
    card.errors = []
    if (card.wrap.datatype !== 'static') {
      if (card.setting.interType === 'system' && card.setting.execute !== 'false' && !card.setting.dataresource) {
        card.errors.push({ level: 0, detail: '未设置数据源!'})
      } else if (card.setting.interType === 'system' && card.setting.execute === 'false' && card.scripts.filter(script => script.status !== 'false').length === 0) {
        card.errors.push({ level: 0, detail: '数据源中无可用脚本!'})
      } else if (!card.setting.primaryKey) {
        card.errors.push({ level: 0, detail: '未设置主键!'})
      } else if (!card.setting.supModule) {
        card.errors.push({ level: 0, detail: '未设置上级组件!'})
      }
    }
    this.setState({
      card: component
      card: card
    })
    component.width = component.wrap.width
    component.name = component.wrap.name
    this.props.updateConfig(component)
    this.props.updateConfig(card)
  }
  changeStyle = () => {
@@ -130,22 +141,8 @@
    if (comIds[0] !== card.uuid || comIds.length !== 1) return
    let _card = {...card, style}
    this.setState({
      card: _card
    })
    
    this.props.updateConfig(_card)
  }
  /**
   * @description 更新搜索条件配置信息
   */
  updateconfig = (config) => {
    this.setState({
      card: config
    })
    this.props.updateConfig(config)
    this.updateComponent(_card)
  }
  getWrapForms = () => {
@@ -155,7 +152,7 @@
  }
  updateWrap = (res) => {
    this.updateconfig({...this.state.card, wrap: res})
    this.updateComponent({...this.state.card, wrap: res})
  }
  clickComponent = (e) => {
@@ -188,7 +185,20 @@
          <ToolOutlined />
        </Popover>
        <CodeContent name={card.name} html={card.html} css={card.css} js={card.js}/>
        <div className="component-name"><div className="center">{card.name}</div></div>
        <div className="component-name">
          <div className="center">
            <div className="title">{card.name}</div>
            <div className="content">
              {card.errors && card.errors.map((err, index) => {
                if (err.level === 0) {
                  return <span key={index} className="error">{err.detail}</span>
                } else {
                  return <span key={index} className="waring">{err.detail};</span>
                }
              })}
            </div>
          </div>
        </div>
      </div>
    )
  }
src/menu/components/editor/braft-editor/index.jsx
@@ -48,7 +48,7 @@
        name: card.name,
        subtype: card.subtype,
        setting: { interType: 'system' },
        wrap: { name: card.name, width: card.width || 24, encryption: 'true', minHeight: 100 },
        wrap: { name: card.name, datatype: 'dynamic', width: card.width || 24, encryption: 'true', minHeight: 100 },
        style: { marginLeft: '8px', marginRight: '8px', marginTop: '8px', marginBottom: '8px' },
        headerStyle: { fontSize: '16px', borderBottomWidth: '1px', borderBottomColor: '#e8e8e8' },
        columns: [],
@@ -69,11 +69,8 @@
        _card.columns = config.columns
        _card.scripts = config.scripts
      }
      this.setState({
        card: _card
      })
      this.props.updateConfig(_card)
      this.updateComponent(_card)
    } else {
      this.setState({
        card: fromJS(card).toJS()
@@ -102,15 +99,29 @@
  /**
   * @description 卡片行外层信息更新(数据源,样式等)
   */
  updateComponent = (component) => {
  updateComponent = (card) => {
    card.width = card.wrap.width
    card.name = card.wrap.name
    card.errors = []
    if (card.wrap.datatype !== 'static') {
      if (card.setting.interType === 'system' && card.setting.execute !== 'false' && !card.setting.dataresource) {
        card.errors.push({ level: 0, detail: '未设置数据源!'})
      } else if (card.setting.interType === 'system' && card.setting.execute === 'false' && card.scripts.filter(script => script.status !== 'false').length === 0) {
        card.errors.push({ level: 0, detail: '数据源中无可用脚本!'})
      } else if (!card.setting.primaryKey) {
        card.errors.push({ level: 0, detail: '未设置主键!'})
      } else if (!card.setting.supModule) {
        card.errors.push({ level: 0, detail: '未设置上级组件!'})
      }
    }
    this.setState({
      card: component
      card: card
    })
    component.width = component.wrap.width
    component.name = component.wrap.name
    this.props.updateConfig(component)
    this.props.updateConfig(card)
  }
  changeStyle = () => {
@@ -130,12 +141,8 @@
    } else {
      return
    }
    this.setState({
      card: _card
    })
    
    this.props.updateConfig(_card)
    this.updateComponent(_card)
  }
  getWrapForms = () => {
@@ -186,7 +193,20 @@
          value={card.wrap.datatype !== 'static' ? '<p class="empty-content">富文本</p>' : card.html}
          encryption="false"
        />
        <div className="component-name"><div className="center">{card.name}</div></div>
        <div className="component-name">
          <div className="center">
            <div className="title">{card.name}</div>
            <div className="content">
              {card.errors && card.errors.map((err, index) => {
                if (err.level === 0) {
                  return <span key={index} className="error">{err.detail}</span>
                } else {
                  return <span key={index} className="waring">{err.detail};</span>
                }
              })}
            </div>
          </div>
        </div>
      </div>
    )
  }
src/menu/components/form/normal-form/index.jsx
@@ -106,10 +106,9 @@
        })
      }
      this.setState({
        card: _card,
        group: _card.subcards[0] || null
      })
      this.props.updateConfig(_card)
      this.updateComponent(_card)
    } else {
      let _card = fromJS(card).toJS()
      this.setState({
@@ -159,15 +158,28 @@
  /**
   * @description 卡片行外层信息更新(数据源,样式等)
   */
  updateComponent = (component) => {
  updateComponent = (card) => {
    card.width = card.wrap.width
    card.name = card.wrap.name
    card.errors = []
    if (card.wrap.datatype !== 'static') {
      if (card.setting.interType === 'system' && card.setting.execute !== 'false' && !card.setting.dataresource) {
        card.errors.push({ level: 0, detail: '未设置数据源!'})
      } else if (card.setting.interType === 'system' && card.setting.execute === 'false' && card.scripts.filter(script => script.status !== 'false').length === 0) {
        card.errors.push({ level: 0, detail: '数据源中无可用脚本!'})
      } else if (!card.setting.primaryKey) {
        card.errors.push({ level: 0, detail: '未设置主键!'})
      } else if (!card.setting.supModule) {
        card.errors.push({ level: 0, detail: '未设置上级组件!'})
      }
    }
    this.setState({
      card: component
      card: card
    })
    component.width = component.wrap.width
    component.name = component.wrap.name
    this.props.updateConfig(component)
    this.props.updateConfig(card)
  }
  /**
@@ -181,9 +193,7 @@
      return item
    })
    this.setState({card})
    this.props.updateConfig(card)
    this.updateComponent(card)
  }
  changeStyle = () => {
@@ -212,12 +222,8 @@
    if (comIds.length !== 1 || comIds[0] !== card.uuid) return
    let _card = {...card, style}
    this.setState({
      card: _card
    })
    
    this.props.updateConfig(_card)
    this.updateComponent(_card)
  }
  addCard = () => {
@@ -237,10 +243,9 @@
    card.subcards.push(newcard)
    
    this.setState({
      card,
      group: newcard
    })
    this.props.updateConfig(card)
    this.updateComponent(card)
  }
  changecards = (list) => {
@@ -250,8 +255,7 @@
      return item
    })
    this.setState({card})
    this.props.updateConfig(card)
    this.updateComponent(card)
  }
  selectGroup = (item) => {
@@ -279,8 +283,8 @@
          _group = card.subcards[0] || null
        }
        _this.setState({card, group: _group})
        _this.props.updateConfig(card)
        _this.setState({group: _group})
        _this.updateComponent(card)
      },
      onCancel() {}
    })
@@ -296,8 +300,8 @@
      return item
    })
    this.setState({card, group})
    this.props.updateConfig(card)
    this.setState({group})
    this.updateComponent(card)
  }
  plusFields = (items) => {
@@ -343,8 +347,8 @@
          }
          return item
        })
        _this.setState({group: config, card})
        _this.props.updateConfig(card)
        _this.setState({group: config})
        _this.updateComponent(card)
      },
      onCancel() {}
    })
@@ -363,12 +367,12 @@
      return item
    })
    this.setState({card, group}, () => {
    this.setState({group}, () => {
      if (newcard) {
        this.handleForm(newcard)
      }
    })
    this.props.updateConfig(card)
    this.updateComponent(card)
  }
  closeForm = (cell) => {
@@ -388,8 +392,8 @@
    confirm({
      content: `确定删除<<${cell.label}>>吗?`,
      onOk() {
        _this.setState({card, group})
        _this.props.updateConfig(card)
        _this.setState({group})
        _this.updateComponent(card)
      },
      onCancel() {}
    })
@@ -731,7 +735,20 @@
          />}
          <FormAction config={card} group={group} updateconfig={this.updateGroup}/>
        </div> : null}
        <div className="component-name"><div className="center">{card.name}</div></div>
        <div className="component-name">
          <div className="center">
            <div className="title">{card.name}</div>
            <div className="content">
              {card.errors && card.errors.map((err, index) => {
                if (err.level === 0) {
                  return <span key={index} className="error">{err.detail}</span>
                } else {
                  return <span key={index} className="waring">{err.detail};</span>
                }
              })}
            </div>
          </div>
        </div>
        <Modal
          title={this.state.dict['model.edit']}
          visible={this.state.visible}
src/menu/components/form/tab-form/index.jsx
@@ -118,10 +118,9 @@
        })
      }
      this.setState({
        card: _card,
        group: _card.subcards[0] || null
      })
      this.props.updateConfig(_card)
      this.updateComponent(_card)
    } else {
      let _card = fromJS(card).toJS()
      this.setState({
@@ -171,15 +170,28 @@
  /**
   * @description 卡片行外层信息更新(数据源,样式等)
   */
  updateComponent = (component) => {
  updateComponent = (card) => {
    card.width = card.wrap.width
    card.name = card.wrap.name
    card.errors = []
    if (card.wrap.datatype !== 'static') {
      if (card.setting.interType === 'system' && card.setting.execute !== 'false' && !card.setting.dataresource) {
        card.errors.push({ level: 0, detail: '未设置数据源!'})
      } else if (card.setting.interType === 'system' && card.setting.execute === 'false' && card.scripts.filter(script => script.status !== 'false').length === 0) {
        card.errors.push({ level: 0, detail: '数据源中无可用脚本!'})
      } else if (!card.setting.primaryKey) {
        card.errors.push({ level: 0, detail: '未设置主键!'})
      } else if (!card.setting.supModule) {
        card.errors.push({ level: 0, detail: '未设置上级组件!'})
      }
    }
    this.setState({
      card: component
      card: card
    })
    component.width = component.wrap.width
    component.name = component.wrap.name
    this.props.updateConfig(component)
    this.props.updateConfig(card)
  }
  /**
@@ -193,9 +205,7 @@
      return item
    })
    this.setState({card})
    this.props.updateConfig(card)
    this.updateComponent(card)
  }
  changeStyle = () => {
@@ -225,11 +235,7 @@
    let _card = {...card, style}
    this.setState({
      card: _card
    })
    this.props.updateConfig(_card)
    this.updateComponent(_card)
  }
  addCard = () => {
@@ -247,10 +253,9 @@
    card.subcards.push(newcard)
    
    this.setState({
      card,
      group: newcard
    })
    this.props.updateConfig(card)
    this.updateComponent(card)
  }
  changecards = (list) => {
@@ -260,8 +265,7 @@
      return item
    })
    this.setState({card})
    this.props.updateConfig(card)
    this.updateComponent(card)
  }
  selectGroup = (item) => {
@@ -285,8 +289,8 @@
          _group = card.subcards[0] || null
        }
        _this.setState({card, group: _group})
        _this.props.updateConfig(card)
        _this.setState({group: _group})
        _this.updateComponent(card)
      },
      onCancel() {}
    })
@@ -302,8 +306,8 @@
      return item
    })
    this.setState({card, group})
    this.props.updateConfig(card)
    this.setState({group})
    this.updateComponent(card)
  }
  plusFields = (items) => {
@@ -349,8 +353,8 @@
          }
          return item
        })
        _this.setState({group: config, card})
        _this.props.updateConfig(card)
        _this.setState({group: config})
        _this.updateComponent(card)
      },
      onCancel() {}
    })
@@ -369,12 +373,12 @@
      return item
    })
    this.setState({card, group}, () => {
    this.setState({group}, () => {
      if (newcard) {
        this.handleForm(newcard)
      }
    })
    this.props.updateConfig(card)
    this.updateComponent(card)
  }
  closeForm = (cell) => {
@@ -394,8 +398,8 @@
    confirm({
      content: `确定删除<<${cell.label}>>吗?`,
      onOk() {
        _this.setState({card, group})
        _this.props.updateConfig(card)
        _this.setState({group})
        _this.updateComponent(card)
      },
      onCancel() {}
    })
@@ -690,8 +694,8 @@
    confirm({
      content: `确定清空表单吗?`,
      onOk() {
        _this.setState({card, group})
        _this.props.updateConfig(card)
        _this.setState({group})
        _this.updateComponent(card)
      },
      onCancel() {}
    })
@@ -763,7 +767,20 @@
          />}
          <FormAction config={card} group={group} updateconfig={this.updateGroup}/>
        </div> : null}
        <div className="component-name"><div className="center">{card.name}</div></div>
        <div className="component-name">
          <div className="center">
            <div className="title">{card.name}</div>
            <div className="content">
              {card.errors && card.errors.map((err, index) => {
                if (err.level === 0) {
                  return <span key={index} className="error">{err.detail}</span>
                } else {
                  return <span key={index} className="waring">{err.detail};</span>
                }
              })}
            </div>
          </div>
        </div>
        <Modal
          title={this.state.dict['model.edit']}
          visible={this.state.visible}
src/menu/components/module/voucher/index.jsx
@@ -49,11 +49,8 @@
        columns: [],
        scripts: [],
      }
      this.setState({
        card: _card
      })
      this.props.updateConfig(_card)
      this.updateComponent(_card)
    } else {
      this.setState({
        card: fromJS(card).toJS()
@@ -82,15 +79,15 @@
  /**
   * @description 卡片行外层信息更新(数据源,样式等)
   */
  updateComponent = (component) => {
  updateComponent = (card) => {
    card.width = card.wrap.width
    card.name = card.wrap.name
    this.setState({
      card: component
      card: card
    })
    component.width = component.wrap.width
    component.name = component.wrap.name
    this.props.updateConfig(component)
    this.props.updateConfig(card)
  }
  changeStyle = () => {
@@ -105,22 +102,8 @@
    if (comIds[0] !== card.uuid || comIds.length !== 1) return
    let _card = {...card, style}
    this.setState({
      card: _card
    })
    
    this.props.updateConfig(_card)
  }
  /**
   * @description 更新搜索条件配置信息
   */
  updateconfig = (config) => {
    this.setState({
      card: config
    })
    this.props.updateConfig(config)
    this.updateComponent(_card)
  }
  getWrapForms = () => {
src/menu/components/table/edit-table/index.jsx
@@ -116,12 +116,8 @@
          _card.wrap.doubleClick = oriUids[_card.wrap.doubleClick] || ''
        }
      }
      this.setState({
        card: _card
      })
      this.filterOrigin(_card)
      this.updateComponent(_card)
    } else {
      this.setState({
        card: fromJS(card).toJS()
@@ -164,31 +160,91 @@
    }
  }
  filterOrigin = (component) => {
    if (component.isNew) {
      let item = fromJS(component).toJS()
      item.cols = item.cols.filter(a => !a.origin)
      delete item.isNew
      this.props.updateConfig(item)
    } else {
      this.props.updateConfig(component)
    }
  }
  /**
   * @description 卡片行外层信息更新(数据源,样式等)
   */
  updateComponent = (component) => {
  updateComponent = (card) => {
    card.width = card.wrap.width
    card.name = card.wrap.name
    if (!window.GLOB.styling || !card.errors) { // 样式修改时不做筛查
      card.errors = []
      if (card.setting.interType === 'system' && card.setting.execute !== 'false' && !card.setting.dataresource) {
        card.errors.push({ level: 0, detail: '未设置数据源!'})
      } else if (card.setting.interType === 'system' && card.setting.execute === 'false' && card.scripts.filter(script => script.status !== 'false').length === 0) {
        card.errors.push({ level: 0, detail: '数据源中无可用脚本!'})
      } else if (!card.setting.primaryKey) {
        card.errors.push({ level: 0, detail: '未设置主键!'})
      } else if (!card.setting.supModule) {
        card.errors.push({ level: 0, detail: '未设置上级组件!'})
      }
      let supModule = card.setting.supModule ? card.setting.supModule[card.setting.supModule.length - 1] || '' : ''
      if (supModule === 'empty') {
        supModule = ''
      }
      let columns = card.columns.map(c => c.field)
      let lowcols = card.columns.map(c => c.field.toLowerCase())
      card.action.forEach(cell => {
        if (cell.OpenType === 'pop' || (cell.OpenType === 'funcbutton' && cell.execMode === 'pop')) {
          if (!cell.modal || cell.modal.fields.length === 0) {
            card.errors.push({ level: 1, detail: `按钮“${cell.label}”中表单尚未添加`})
          } else {
            cell.modal.fields.forEach(m => {
              if (m.type === 'linkMain' && !supModule) {
                card.errors.push({ level: 1, detail: `按钮“${cell.label}”中关联主表表单“${m.label}”无效`})
              } else if (m.field && !columns.includes(m.field) && lowcols.includes(m.field.toLowerCase())) {
                card.errors.push({ level: 1, detail: `按钮“${cell.label}”中表单“${m.label}”大小写与字段集不一致`})
              }
            })
          }
        }
      })
      card.cols.forEach(col => {
        if (col.type === 'action') {
          col.elements.forEach(cell => {
            if (cell.OpenType === 'pop' || (cell.OpenType === 'funcbutton' && cell.execMode === 'pop')) {
              if (!cell.modal || cell.modal.fields.length === 0) {
                card.errors.push({ level: 1, detail: `按钮“${cell.label}”中表单尚未添加`})
              } else {
                cell.modal.fields.forEach(m => {
                  if (m.type === 'linkMain' && !supModule) {
                    card.errors.push({ level: 1, detail: `按钮“${cell.label}”中关联主表表单“${m.label}”无效`})
                  } else if (m.field && !columns.includes(m.field) && lowcols.includes(m.field.toLowerCase())) {
                    card.errors.push({ level: 1, detail: `按钮“${cell.label}”中表单“${m.label}”大小写与字段集不一致`})
                  }
                })
              }
            }
          })
        } else if (col.type === 'custom') {
          col.elements.forEach(cell => {
            if (cell.datatype === 'dynamic' && cell.field && !columns.includes(cell.field)) {
              card.errors.push({ level: 1, detail: `显示列“${col.label}”中动态字段“${cell.field}”无效`})
            }
          })
        } else if (col.field && !columns.includes(col.field)) {
          card.errors.push({ level: 1, detail: `显示列“${col.label}”中字段“${col.field}”无效`})
        }
      })
    }
    this.setState({
      card: component
      card: card
    })
    component.width = component.wrap.width
    component.name = component.wrap.name
    let _card = card.isNew ? fromJS(card).toJS() : card
    if (_card.isNew) {
      _card.cols = _card.cols.filter(a => !a.origin)
    this.filterOrigin(component)
      delete _card.isNew
    }
    this.props.updateConfig(_card)
  }
  changeStyle = () => {
@@ -222,12 +278,8 @@
    _card.wrap.color = color
    _card.wrap.fontSize = fontSize
    _card.wrap.fontWeight = fontWeight
    this.setState({
      card: _card
    })
    
    this.filterOrigin(_card)
    this.updateComponent(_card)
  }
  addColumns = () => {
@@ -272,16 +324,6 @@
    MKEmitter.emit('addButton', card.uuid, newcard)
  }
  /**
   * @description 更新搜索条件配置信息
   */
  updateconfig = (config) => {
    this.setState({
      card: config
    })
    this.filterOrigin(config)
  }
  setSubConfig = (item) => {
    const { card, appType } = this.state
    let btn = fromJS(item).toJS()
@@ -318,8 +360,7 @@
      return cell
    })
    this.setState({card})
    this.filterOrigin(card)
    this.updateComponent(card)
  }
  getWrapForms = () => {
@@ -376,10 +417,23 @@
        } trigger="hover">
          <ToolOutlined />
        </Popover>
        <SearchComponent config={card} updatesearch={this.updateconfig}/>
        <SearchComponent config={card} updatesearch={this.updateComponent}/>
        <ActionComponent type="editable" config={card} setSubConfig={this.setSubConfig} updateaction={this.updateComponent}/>
        <ColumnComponent config={card} updatecolumn={this.updateconfig}/>
        <div className="component-name"><div className="center">{card.name}</div></div>
        <ColumnComponent config={card} updatecolumn={this.updateComponent}/>
        <div className="component-name">
          <div className="center">
            <div className="title">{card.name}</div>
            <div className="content">
              {card.errors && card.errors.map((err, index) => {
                if (err.level === 0) {
                  return <span key={index} className="error">{err.detail}</span>
                } else {
                  return <span key={index} className="waring">{err.detail};</span>
                }
              })}
            </div>
          </div>
        </div>
      </div>
    )
  }
src/menu/components/table/normal-table/index.jsx
@@ -1,7 +1,7 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import { is, fromJS } from 'immutable'
import { Popover, notification } from 'antd'
import { Popover } from 'antd'
import { PlusOutlined, PlusCircleOutlined, PlusSquareOutlined, EditOutlined, ToolOutlined, DeleteOutlined, FontColorsOutlined } from '@ant-design/icons'
import asyncComponent from '@/utils/asyncComponent'
@@ -21,7 +21,7 @@
const CopyComponent = asyncIconComponent(() => import('@/menu/components/share/copycomponent'))
const UserComponent = asyncIconComponent(() => import('@/menu/components/share/usercomponent'))
const PasteComponent = asyncIconComponent(() => import('@/menu/components/share/pastecomponent'))
const LogComponent = asyncIconComponent(() => import('@/menu/components/share/logcomponent'))
// const LogComponent = asyncIconComponent(() => import('@/menu/components/share/logcomponent'))
const ColumnComponent = asyncComponent(() => import('./columns'))
class TableCardEditComponent extends Component {
@@ -128,12 +128,8 @@
        _card.search = []
        _card.action = _card.action.filter(a => !a.origin)
      }
      this.setState({
        card: _card
      })
      this.filterOrigin(_card)
      this.updateComponent(_card)
    } else {
      let _card = fromJS(card).toJS()
      if (appType === 'mob') {
@@ -149,7 +145,7 @@
  componentDidMount () {
    MKEmitter.addListener('submitStyle', this.getStyle)
    MKEmitter.addListener('submitModal', this.handleSave)
    MKEmitter.addListener('logButton', this.logButton)
    // MKEmitter.addListener('logButton', this.logButton)
    MKEmitter.addListener('completeSave', this.completeSave)
  }
@@ -166,7 +162,7 @@
    }
    MKEmitter.removeListener('submitStyle', this.getStyle)
    MKEmitter.removeListener('submitModal', this.handleSave)
    MKEmitter.removeListener('logButton', this.logButton)
    // MKEmitter.removeListener('logButton', this.logButton)
    MKEmitter.removeListener('completeSave', this.completeSave)
  }
@@ -202,48 +198,116 @@
    return col
  }
  filterOrigin = (component) => {
    if (component.isNew) {
      let item = fromJS(component).toJS()
      item.search = item.search.filter(a => !a.origin)
      item.action = item.action.filter(a => !a.origin)
      item.cols = item.cols.filter(a => !a.origin)
      delete item.isNew
      this.props.updateConfig(item)
    } else {
      this.props.updateConfig(component)
    }
  }
  /**
   * @description 卡片行外层信息更新(数据源,样式等)
   */
  updateComponent = (component) => {
    this.setState({
      card: component
    })
  updateComponent = (card) => {
    card.width = card.wrap.width
    card.name = card.wrap.name
    component.width = component.wrap.width
    component.name = component.wrap.name
    this.filterOrigin(component)
  }
  logButton = (id, item) => {
    const { card } = this.state
    if (id !== card.uuid) return
    let btnlog = card.btnlog || []
    btnlog.push(item)
    if (!window.GLOB.styling || !card.errors) { // 样式修改时不做筛查
      card.errors = []
      if (card.setting.interType === 'system' && card.setting.execute !== 'false' && !card.setting.dataresource) {
        card.errors.push({ level: 0, detail: '未设置数据源!'})
      } else if (card.setting.interType === 'system' && card.setting.execute === 'false' && card.scripts.filter(script => script.status !== 'false').length === 0) {
        card.errors.push({ level: 0, detail: '数据源中无可用脚本!'})
      } else if (!card.setting.primaryKey) {
        card.errors.push({ level: 0, detail: '未设置主键!'})
      } else if (!card.setting.supModule) {
        card.errors.push({ level: 0, detail: '未设置上级组件!'})
      }
      let supModule = card.setting.supModule ? card.setting.supModule[card.setting.supModule.length - 1] || '' : ''
      if (supModule === 'empty') {
        supModule = ''
      }
      let doubleClick = card.wrap.doubleClick || ''
      let columns = card.columns.map(c => c.field)
      let lowcols = card.columns.map(c => c.field.toLowerCase())
      card.action.forEach(cell => {
        if (cell.OpenType === 'pop' || (cell.OpenType === 'funcbutton' && cell.execMode === 'pop')) {
          if (!cell.modal || cell.modal.fields.length === 0) {
            card.errors.push({ level: 1, detail: `按钮“${cell.label}”中表单尚未添加`})
          } else {
            cell.modal.fields.forEach(m => {
              if (m.type === 'linkMain' && !supModule) {
                card.errors.push({ level: 1, detail: `按钮“${cell.label}”中关联主表表单“${m.label}”无效`})
              } else if (m.field && !columns.includes(m.field) && lowcols.includes(m.field.toLowerCase())) {
                card.errors.push({ level: 1, detail: `按钮“${cell.label}”中表单“${m.label}”大小写与字段集不一致`})
              }
            })
          }
        }
        if (doubleClick === cell.uuid) {
          doubleClick = ''
        }
      })
      card.cols.forEach(col => {
        if (col.type === 'action') {
          col.elements.forEach(cell => {
            if (cell.OpenType === 'pop' || (cell.OpenType === 'funcbutton' && cell.execMode === 'pop')) {
              if (!cell.modal || cell.modal.fields.length === 0) {
                card.errors.push({ level: 1, detail: `按钮“${cell.label}”中表单尚未添加`})
              } else {
                cell.modal.fields.forEach(m => {
                  if (m.type === 'linkMain' && !supModule) {
                    card.errors.push({ level: 1, detail: `按钮“${cell.label}”中关联主表表单“${m.label}”无效`})
                  } else if (m.field && !columns.includes(m.field) && lowcols.includes(m.field.toLowerCase())) {
                    card.errors.push({ level: 1, detail: `按钮“${cell.label}”中表单“${m.label}”大小写与字段集不一致`})
                  }
                })
              }
            }
            if (doubleClick === cell.uuid) {
              doubleClick = ''
            }
          })
        } else if (col.type === 'custom') {
          col.elements.forEach(cell => {
            if (cell.datatype === 'dynamic' && cell.field && !columns.includes(cell.field)) {
              card.errors.push({ level: 1, detail: `显示列“${col.label}”中动态字段“${cell.field}”无效`})
            }
          })
        } else if (col.field && !columns.includes(col.field)) {
          card.errors.push({ level: 1, detail: `显示列“${col.label}”中字段“${col.field}”无效`})
        }
      })
      if (doubleClick) {
        card.errors.push({ level: 1, detail: `绑定的双击按钮已删除`})
      }
    }
    this.setState({
      card: {...card, btnlog}
      card: card
    })
    this.filterOrigin({...card, btnlog})
    let _card = card.isNew ? fromJS(card).toJS() : card
    if (_card.isNew) {
      _card.cols = _card.cols.filter(a => !a.origin)
      _card.search = _card.search.filter(a => !a.origin)
      _card.action = _card.action.filter(a => !a.origin)
      delete _card.isNew
    }
    this.props.updateConfig(_card)
  }
  // logButton = (id, item) => {
  //   const { card } = this.state
  //   if (id !== card.uuid) return
  //   let btnlog = card.btnlog || []
  //   btnlog.push(item)
  //   this.updateComponent({...card, btnlog})
  // }
  changeStyle = () => {
    const { card } = this.state
@@ -277,11 +341,7 @@
    _card.wrap.fontSize = fontSize
    _card.wrap.fontWeight = fontWeight
    this.setState({
      card: _card
    })
    this.filterOrigin(_card)
    this.updateComponent(_card)
  }
  addColumns = () => {
@@ -326,16 +386,6 @@
    MKEmitter.emit('addButton', card.uuid, newcard)
  }
  /**
   * @description 更新搜索条件配置信息
   */
  updateconfig = (config) => {
    this.setState({
      card: config
    })
    this.filterOrigin(config)
  }
  setSubConfig = (item) => {
    const { card, appType } = this.state
    let btn = fromJS(item).toJS()
@@ -372,49 +422,46 @@
      return cell
    })
    this.setState({card})
    this.filterOrigin(card)
    this.updateComponent(card)
  }
  handleLog = (type, logs, item) => {
    let card = fromJS(this.state.card).toJS()
  // handleLog = (type, logs, item) => {
  //   let card = fromJS(this.state.card).toJS()
    if (type === 'revert') {
      let done = false
      if (item.$parentId) {
        card.cols.forEach(col => {
          if (col.type !== 'action') return
          if (item.$parentId === col.uuid) {
            col.elements = col.elements ? [...col.elements, item] : [item]
            done = true
          }
        })
      }
  //   if (type === 'revert') {
  //     let done = false
  //     if (item.$parentId) {
  //       card.cols.forEach(col => {
  //         if (col.type !== 'action') return
  //         if (item.$parentId === col.uuid) {
  //           col.elements = col.elements ? [...col.elements, item] : [item]
  //           done = true
  //         }
  //       })
  //     }
      if (!done) {
        card.action = card.action ? [...card.action, item] : [item]
      }
  //     if (!done) {
  //       card.action = card.action ? [...card.action, item] : [item]
  //     }
      card.btnlog = logs
  //     card.btnlog = logs
      this.setState({ card })
      this.filterOrigin(card)
      notification.success({
        top: 92,
        message: '恢复成功!',
        duration: 2
      })
    } else {
      card.btnlog = logs
      this.setState({ card })
      this.filterOrigin(card)
      notification.success({
        top: 92,
        message: '清除成功!',
        duration: 2
      })
    }
  }
  //     this.updateComponent(card)
  //     notification.success({
  //       top: 92,
  //       message: '恢复成功!',
  //       duration: 2
  //     })
  //   } else {
  //     card.btnlog = logs
  //     this.updateComponent(card)
  //     notification.success({
  //       top: 92,
  //       message: '清除成功!',
  //       duration: 2
  //     })
  //   }
  // }
  getWrapForms = () => {
    const { wrap, action, columns, cols } = this.state.card
@@ -469,7 +516,7 @@
            <CopyComponent type="normaltable" card={card}/>
            <PasteComponent config={card} options={options} updateConfig={this.updateComponent} />
            <FontColorsOutlined className="style" title="调整样式" onClick={this.changeStyle}/>
            <LogComponent btnlog={card.btnlog || []} handlelog={this.handleLog} />
            {/* <LogComponent btnlog={card.btnlog || []} handlelog={this.handleLog} /> */}
            <UserComponent config={card}/>
            <DeleteOutlined className="close" title="删除组件" onClick={() => this.props.deletecomponent(card.uuid)} />
            <SettingComponent config={card} updateConfig={this.updateComponent} />
@@ -477,10 +524,23 @@
        } trigger="hover">
          <ToolOutlined />
        </Popover>
        <SearchComponent config={card} updatesearch={this.updateconfig}/>
        <SearchComponent config={card} updatesearch={this.updateComponent}/>
        <ActionComponent config={card} setSubConfig={this.setSubConfig} updateaction={this.updateComponent}/>
        <ColumnComponent config={card} updatecolumn={this.updateconfig}/>
        <div className="component-name"><div className="center">{card.name}</div></div>
        <ColumnComponent config={card} updatecolumn={this.updateComponent}/>
        <div className="component-name">
          <div className="center">
            <div className="title">{card.name}</div>
            <div className="content">
              {card.errors && card.errors.map((err, index) => {
                if (err.level === 0) {
                  return <span key={index} className="error">{err.detail}</span>
                } else {
                  return <span key={index} className="waring">{err.detail};</span>
                }
              })}
            </div>
          </div>
        </div>
      </div>
    )
  }
src/menu/components/timeline/normal-timeline/index.jsx
@@ -82,10 +82,8 @@
          return scard
        })
      }
      this.setState({
        card: _card
      })
      this.props.updateConfig(_card)
      this.updateComponent(_card)
    } else {
      this.setState({
        card: fromJS(card).toJS()
@@ -114,15 +112,57 @@
  /**
   * @description 卡片行外层信息更新(数据源,样式等)
   */
  updateComponent = (component) => {
  updateComponent = (card) => {
    card.width = card.wrap.width
    card.name = card.wrap.name
    if (!window.GLOB.styling || !card.errors) { // 样式修改时不做筛查
      card.errors = []
      if (card.setting.interType === 'system' && card.setting.execute !== 'false' && !card.setting.dataresource) {
        card.errors.push({ level: 0, detail: '未设置数据源!'})
      } else if (card.setting.interType === 'system' && card.setting.execute === 'false' && card.scripts.filter(script => script.status !== 'false').length === 0) {
        card.errors.push({ level: 0, detail: '数据源中无可用脚本!'})
      } else if (!card.setting.primaryKey) {
        card.errors.push({ level: 0, detail: '未设置主键!'})
      } else if (!card.setting.supModule) {
        card.errors.push({ level: 0, detail: '未设置上级组件!'})
      }
      let supModule = card.setting.supModule ? card.setting.supModule[card.setting.supModule.length - 1] || '' : ''
      if (supModule === 'empty') {
        supModule = ''
      }
      let columns = card.columns.map(c => c.field)
      let lowcols = card.columns.map(c => c.field.toLowerCase())
      card.subcards.forEach(col => {
        col.elements.forEach(cell => {
          if (cell.eleType === 'button') {
            if (cell.OpenType === 'pop' || (cell.OpenType === 'funcbutton' && cell.execMode === 'pop')) {
              if (!cell.modal || cell.modal.fields.length === 0) {
                card.errors.push({ level: 1, detail: `按钮“${cell.label}”中表单尚未添加`})
              } else {
                cell.modal.fields.forEach(m => {
                  if (m.type === 'linkMain' && !supModule) {
                    card.errors.push({ level: 1, detail: `按钮“${cell.label}”中关联主表表单“${m.label}”无效`})
                  } else if (m.field && !columns.includes(m.field) && lowcols.includes(m.field.toLowerCase())) {
                    card.errors.push({ level: 1, detail: `按钮“${cell.label}”中表单“${m.label}”大小写与字段集不一致`})
                  }
                })
              }
            }
          } else if (cell.datatype === 'dynamic' && cell.field && !columns.includes(cell.field)) {
            card.errors.push({ level: 1, detail: `卡片中动态字段“${cell.field}”无效`})
          }
        })
      })
    }
    this.setState({
      card: component
      card: card
    })
    component.width = component.wrap.width
    component.name = component.wrap.name
    this.props.updateConfig(component)
    this.props.updateConfig(card)
  }
  updateCard = (cell) => {
@@ -133,9 +173,7 @@
      return item
    })
    this.setState({card})
    this.props.updateConfig(card)
    this.updateComponent(card)
  }
  changeStyle = () => {
@@ -150,12 +188,8 @@
    if (comIds.length !== 1 || comIds[0] !== card.uuid) return
    let _card = {...card, style}
    this.setState({
      card: _card
    })
    
    this.props.updateConfig(_card)
    this.updateComponent(_card)
  }
  getWrapForms = () => {
@@ -192,7 +226,20 @@
        </Popover>
        <NormalHeader hideSearch="true" config={card} updateComponent={this.updateComponent}/>
        {card.subcards.map(subcard => (<CardSimpleComponent key={subcard.uuid} cards={card} card={subcard} updateElement={this.updateCard}/>))}
        <div className="component-name"><div className="center">{card.name}</div></div>
        <div className="component-name">
          <div className="center">
            <div className="title">{card.name}</div>
            <div className="content">
              {card.errors && card.errors.map((err, index) => {
                if (err.level === 0) {
                  return <span key={index} className="error">{err.detail}</span>
                } else {
                  return <span key={index} className="waring">{err.detail};</span>
                }
              })}
            </div>
          </div>
        </div>
      </div>
    )
  }
src/menu/components/tree/antd-tree/index.jsx
@@ -70,10 +70,7 @@
        _card.scripts = config.scripts
      }
      
      this.setState({
        card: _card
      })
      this.props.updateConfig(_card)
      this.updateComponent(_card)
    } else {
      this.setState({
        card: fromJS(card).toJS()
@@ -102,15 +99,31 @@
  /**
   * @description 卡片行外层信息更新(数据源,样式等)
   */
  updateComponent = (component) => {
  updateComponent = (card) => {
    card.width = card.wrap.width
    card.name = card.wrap.name
    card.errors = []
    if (card.setting.interType === 'system' && card.setting.execute !== 'false' && !card.setting.dataresource) {
      card.errors.push({ level: 0, detail: '未设置数据源!'})
    } else if (card.setting.interType === 'system' && card.setting.execute === 'false' && card.scripts.filter(script => script.status !== 'false').length === 0) {
      card.errors.push({ level: 0, detail: '数据源中无可用脚本!'})
    } else if (!card.setting.primaryKey) {
      card.errors.push({ level: 0, detail: '未设置主键!'})
    } else if (!card.setting.supModule) {
      card.errors.push({ level: 0, detail: '未设置上级组件!'})
    }
    if (!card.wrap.parentField || !card.wrap.valueField || !card.wrap.labelField) {
      card.errors.push({ level: 0, detail: '未设置基本信息!'})
    }
    this.setState({
      card: component
      card: card
    })
    component.width = component.wrap.width
    component.name = component.wrap.name
    this.props.updateConfig(component)
    this.props.updateConfig(card)
  }
  changeStyle = () => {
@@ -126,21 +139,7 @@
    let _card = {...card, style}
    this.setState({
      card: _card
    })
    this.props.updateConfig(_card)
  }
  /**
   * @description 更新搜索条件配置信息
   */
  updateconfig = (config) => {
    this.setState({
      card: config
    })
    this.props.updateConfig(config)
    this.updateComponent(_card)
  }
  getWrapForms = () => {
@@ -194,7 +193,20 @@
            </TreeNode>
          </Tree>
        </div>
        <div className="component-name"><div className="center">{card.name}</div></div>
        <div className="component-name">
          <div className="center">
            <div className="title">{card.name}</div>
            <div className="content">
              {card.errors && card.errors.map((err, index) => {
                if (err.level === 0) {
                  return <span key={index} className="error">{err.detail}</span>
                } else {
                  return <span key={index} className="waring">{err.detail};</span>
                }
              })}
            </div>
          </div>
        </div>
      </div>
    )
  }
src/menu/popview/index.jsx
@@ -560,32 +560,14 @@
        } else if (item.type === 'group') {
          check(item.components)
          return
        } else if (!item.errors || item.errors.length === 0) {
          return
        }
        if (['propcard', 'brafteditor', 'sandbox', 'stepform', 'tabform'].includes(item.subtype) && item.wrap.datatype === 'static') return
        if (['balcony'].includes(item.type) && item.wrap.datatype === 'static') return
        if (item.setting) {
          if (item.setting.interType === 'system' && item.setting.execute !== 'false' && !item.setting.dataresource) {
            error = `组件《${item.name}》未设置数据源!`
          } else if (item.setting.interType === 'system' && item.setting.execute === 'false' && item.scripts.length === 0) {
            error = `组件《${item.name}》未设置数据源!`
          } else if (!item.setting.primaryKey) {
            error = `组件《${item.name}》未设置主键!`
          } else if (!item.setting.supModule && item.type !== 'balcony') {
            error = `组件《${item.name}》未设置上级组件!`
          }
        }
        if (item.type === 'bar' || item.type === 'line' || item.type === 'pie') {
          if (!item.plot.Xaxis) {
            error = `组件《${item.name}》图表字段尚未设置!`
          }
        } else if (item.type === 'dashboard' && !item.plot.valueField) {
          error = `组件《${item.name}》显示值尚未设置!`
        } else if (item.type === 'scatter' && (!item.plot.Xaxis || !item.plot.Yaxis || !item.plot.gender)) {
          error = `组件《${item.name}》坐标轴尚未设置!`
        } else if (item.type === 'tree' && (!item.wrap.valueField || !item.wrap.labelField || !item.wrap.parentField)) {
          error = `组件《${item.name}》基本信息尚未设置!`
        }
        item.errors.forEach(err => {
          if (err.level !== 0 || error) return
          error = `组件《${item.name}》${err.detail}`
        })
      })
    }
src/menu/stylecontroller/index.jsx
@@ -87,6 +87,7 @@
      borposition: 'outer',
      backgroundImage
    })
    window.GLOB.styling = true
  }
  onCloseDrawer = () => {
@@ -126,6 +127,7 @@
      options: [],
      backgroundImage: ''
    })
    window.GLOB.styling = false
  }
  updateStyle = (style) => {
src/pc/components/login/normal-login/index.jsx
@@ -65,10 +65,8 @@
        _card.wrap.name = card.name
        _card.style = config.style
      }
      this.setState({
        card: _card
      })
      this.props.updateConfig(_card)
      this.updateComponent(_card)
    } else {
      let _card = fromJS(card).toJS()
      if (_card.loginWays.length === 2) {
@@ -104,15 +102,21 @@
  /**
   * @description 卡片行外层信息更新(数据源,样式等)
   */
  updateComponent = (component) => {
  updateComponent = (card) => {
    card.width = card.wrap.width
    card.name = card.wrap.name
    card.errors = []
    if (!card.wrap.linkmenu) {
      card.errors.push({ level: 0, detail: '登录后跳转菜单未设置!'})
    }
    this.setState({
      card: component
      card: card
    })
    component.width = component.wrap.width
    component.name = component.wrap.name
    this.props.updateConfig(component)
    this.props.updateConfig(card)
  }
  changeStyle = () => {
@@ -127,12 +131,8 @@
    if (comIds.length !== 1 || comIds[0] !== card.uuid) return
    let _card = {...card, style}
    this.setState({
      card: _card
    })
    
    this.props.updateConfig(_card)
    this.updateComponent(_card)
  }
  clickComponent = (e) => {
@@ -188,7 +188,20 @@
          <ToolOutlined />
        </Popover>
        <LoginForm loginWays={card.loginWays} wrap={card.wrap} />
        <div className="component-name"><div className="center">{card.name}</div></div>
        <div className="component-name">
          <div className="center">
            <div className="title">{card.name}</div>
            <div className="content">
              {card.errors && card.errors.map((err, index) => {
                if (err.level === 0) {
                  return <span key={index} className="error">{err.detail}</span>
                } else {
                  return <span key={index} className="waring">{err.detail};</span>
                }
              })}
            </div>
          </div>
        </div>
      </div>
    )
  }
src/views/appmanage/scriptform/index.jsx
@@ -17,7 +17,7 @@
  }
  state = {
    type: 'subapp',
    type: 'view',
    sublist: [],
    views: [],
    appId: '',
@@ -166,7 +166,7 @@
              </Tooltip>
            }>
              {getFieldDecorator('VType', {
                initialValue: 'subapp',
                initialValue: 'view',
                rules: [{
                  required: true,
                  message: '请选择类型!'
src/views/menudesign/index.jsx
@@ -975,6 +975,7 @@
    let check = (components) => {
      components.forEach(item => {
        if (error) return
        if (item.type === 'tabs') {
          item.subtabs.forEach(tab => {
            check(tab.components)
@@ -983,46 +984,14 @@
        } else if (item.type === 'group') {
          check(item.components)
          return
        } else if (item.subtype === 'propcard' && item.subcards.length === 0) {
          error = `组件《${item.name}》中卡片不可为空!`
        } else if (!item.errors || item.errors.length === 0) {
          return
        }
        if (['voucher'].includes(item.subtype)) return
        if (['propcard', 'brafteditor', 'sandbox', 'stepform', 'tabform'].includes(item.subtype) && item.wrap.datatype === 'static') return
        if (['balcony'].includes(item.type) && item.wrap.datatype === 'static') return
        if (item.setting) {
          if (item.setting.interType === 'system' && item.setting.execute !== 'false' && !item.setting.dataresource) {
            error = `组件《${item.name}》未设置数据源!`
          } else if (item.setting.interType === 'system' && item.setting.execute === 'false' && item.scripts.length === 0) {
            error = `组件《${item.name}》未设置数据源!`
          } else if (!item.setting.primaryKey) {
            error = `组件《${item.name}》未设置主键!`
          } else if (!item.setting.supModule && item.type !== 'balcony' && (!item.wrap || item.wrap.supType !== 'multi')) {
            error = `组件《${item.name}》未设置上级组件!`
          }
        }
        if (item.type === 'bar' || item.type === 'line' || item.type === 'pie') {
          if (!item.plot.Xaxis) {
            error = `组件《${item.name}》图表字段尚未设置!`
          }
        } else if (item.type === 'dashboard' && !item.plot.valueField) {
          error = `组件《${item.name}》显示值尚未设置!`
        } else if (item.type === 'scatter' && (!item.plot.Xaxis || !item.plot.Yaxis || !item.plot.gender)) {
          error = `组件《${item.name}》坐标轴尚未设置!`
        } else if (item.type === 'tree' && (!item.wrap.valueField || !item.wrap.labelField || !item.wrap.parentField)) {
          error = `组件《${item.name}》基本信息尚未设置!`
        } else if (item.type === 'table' && item.wrap.doubleClick) {
          let _actions = [...item.action]
          item.cols.forEach(col => {
            if (col.type !== 'action') return
            _actions.push(...col.elements)
          })
          if (_actions.findIndex((m) => m.uuid === item.wrap.doubleClick) === -1) {
            error = `组件《${item.name}》绑定的双击按钮已删除!`
          }
        }
        item.errors.forEach(err => {
          if (err.level !== 0 || error) return
          error = `组件《${item.name}》${err.detail}`
        })
      })
    }
src/views/menudesign/index.scss
@@ -26,7 +26,7 @@
    right: 0;
    top: 0;
    bottom: 0;
    background: rgba(255, 255, 255, 0.8);
    background: rgba(255, 255, 255, 0.9);
    border: 1px solid #1890ff;
    .center {
      position: absolute;
@@ -35,6 +35,18 @@
      top: 50%;
      color: #1890ff;
      transform: translate(-50%, -50%);
      max-width: 70%;
      .title {
        text-align: center;
      }
    }
    .error {
      text-align: center;
      color: red;
      display: block;
    }
    .waring {
      color: orange;
    }
  }
  >.menu-body {
src/views/mobdesign/index.jsx
@@ -1631,42 +1631,15 @@
          if (!item.wrap.field) {
            error = `搜索条件《${item.name}》未设置搜索字段!`
          }
        } else if (item.subtype === 'propcard' && item.subcards.length === 0) {
          error = `组件《${item.name}》中卡片不可为空!`
          return
        } else if (item.type === 'login' && !item.wrap.linkmenu && item.wrap.link !== 'menu') {
          error = '登录组件未设置关联菜单!'
          return
        }
        if (item.wrap && item.wrap.pagestyle === 'slide') {
          swipes.push(item.name)
        }
        if (['voucher'].includes(item.subtype)) return
        if (['propcard', 'brafteditor', 'sandbox', 'tabbar', 'stepform', 'tabform'].includes(item.subtype) && item.wrap.datatype === 'static') return
        if (['balcony'].includes(item.type) && item.wrap.datatype === 'static') return
        if (['menubar'].includes(item.type) && item.wrap.datatype !== 'dynamic') return
        if (item.setting) {
          if (item.setting.interType === 'system' && item.setting.execute !== 'false' && !item.setting.dataresource) {
            error = `组件《${item.name}》未设置数据源!`
          } else if (item.setting.interType === 'system' && item.setting.execute === 'false' && item.scripts.length === 0) {
            error = `组件《${item.name}》未设置数据源!`
          } else if (!item.setting.primaryKey) {
            error = `组件《${item.name}》未设置主键!`
          } else if (!item.setting.supModule && !['navbar', 'balcony', 'menubar'].includes(item.type)) {
            error = `组件《${item.name}》未设置上级组件!`
          }
        }
        if (item.type === 'bar' || item.type === 'line' || item.type === 'pie') {
          if (!item.plot.Xaxis) {
            error = `组件《${item.name}》图表字段尚未设置!`
          }
        } else if (item.type === 'dashboard' && !item.plot.valueField) {
          error = `组件《${item.name}》显示值尚未设置!`
        } else if (item.type === 'scatter' && (!item.plot.Xaxis || !item.plot.Yaxis || !item.plot.gender)) {
          error = `组件《${item.name}》坐标轴尚未设置!`
        }
        item.errors && item.errors.forEach(err => {
          if (err.level !== 0 || error) return
          error = `组件《${item.name}》${err.detail}`
        })
      })
    }
src/views/mobdesign/index.scss
@@ -17,7 +17,7 @@
    right: 0;
    top: 0;
    bottom: 0;
    background: rgba(255, 255, 255, 0.8);
    background: rgba(255, 255, 255, 0.9);
    border: 1px solid #1890ff;
    .center {
      position: absolute;
@@ -26,6 +26,18 @@
      top: 50%;
      color: #1890ff;
      transform: translate(-50%, -50%);
      max-width: 70%;
      .title {
        text-align: center;
      }
    }
    .error {
      text-align: center;
      color: red;
      display: block;
    }
    .waring {
      color: orange;
    }
  }
src/views/pcdesign/index.jsx
@@ -1678,49 +1678,14 @@
        } else if (item.type === 'group') {
          check(item.components)
          return
        } else if (item.subtype === 'propcard' && item.subcards.length === 0) {
          error = `组件《${item.name}》中卡片不可为空!`
          return
        } else if (item.type === 'login' && !item.wrap.linkmenu && item.wrap.link !== 'menu') {
          error = '登录组件未设置关联菜单!'
        } else if (!item.errors || item.errors.length === 0) {
          return
        }
        
        if (['voucher'].includes(item.subtype)) return
        if (['propcard', 'brafteditor', 'sandbox', 'stepform', 'tabform'].includes(item.subtype) && item.wrap.datatype === 'static') return
        if (['balcony'].includes(item.type) && item.wrap.datatype === 'static') return
        if (item.setting) {
          if (item.setting.interType === 'system' && item.setting.execute !== 'false' && !item.setting.dataresource) {
            error = `组件《${item.name}》未设置数据源!`
          } else if (item.setting.interType === 'system' && item.setting.execute === 'false' && item.scripts.length === 0) {
            error = `组件《${item.name}》未设置数据源!`
          } else if (!item.setting.primaryKey) {
            error = `组件《${item.name}》未设置主键!`
          } else if (!item.setting.supModule && item.type !== 'balcony' && (!item.wrap || item.wrap.supType !== 'multi')) {
            error = `组件《${item.name}》未设置上级组件!`
          }
        }
        if (item.type === 'bar' || item.type === 'line' || item.type === 'pie') {
          if (!item.plot.Xaxis) {
            error = `组件《${item.name}》图表字段尚未设置!`
          }
        } else if (item.type === 'dashboard' && !item.plot.valueField) {
          error = `组件《${item.name}》显示值尚未设置!`
        } else if (item.type === 'scatter' && (!item.plot.Xaxis || !item.plot.Yaxis || !item.plot.gender)) {
          error = `组件《${item.name}》坐标轴尚未设置!`
        } else if (item.type === 'tree' && (!item.wrap.valueField || !item.wrap.labelField || !item.wrap.parentField)) {
          error = `组件《${item.name}》基本信息尚未设置!`
        } else if (item.type === 'table' && item.wrap.doubleClick) {
          let _actions = [...item.action]
          item.cols.forEach(col => {
            if (col.type !== 'action') return
            _actions.push(...col.elements)
          })
          if (_actions.findIndex((m) => m.uuid === item.wrap.doubleClick) === -1) {
            error = `组件《${item.name}》绑定的双击按钮已删除!`
          }
        }
        item.errors.forEach(err => {
          if (err.level !== 0 || error) return
          error = `组件《${item.name}》${err.detail}`
        })
      })
    }
src/views/pcdesign/index.scss
@@ -21,7 +21,7 @@
    right: 0;
    top: 0;
    bottom: 0;
    background: rgba(255, 255, 255, 0.8);
    background: rgba(255, 255, 255, 0.9);
    border: 1px solid #1890ff;
    .center {
      position: absolute;
@@ -30,6 +30,18 @@
      top: 50%;
      color: #1890ff;
      transform: translate(-50%, -50%);
      max-width: 70%;
      .title {
        text-align: center;
      }
    }
    .error {
      text-align: center;
      color: red;
      display: block;
    }
    .waring {
      color: orange;
    }
  }