king
2022-10-14 74e5d38d9a0e94421ceceea37c4677e5b57364ba
2022-10-14
61个文件已修改
7个文件已添加
1846 ■■■■ 已修改文件
src/locales/en-US/model.js 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/locales/zh-CN/model.js 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/card/balcony/index.jsx 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/card/data-card/index.jsx 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/card/prop-card/index.jsx 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/card/table-card/index.jsx 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/carousel/data-card/index.jsx 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/carousel/prop-card/index.jsx 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/chart/antv-bar/index.jsx 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/chart/antv-dashboard/index.jsx 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/chart/antv-pie/index.jsx 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/chart/antv-scatter/index.jsx 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/chart/chart-custom/index.jsx 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/code/sandbox/index.jsx 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/editor/braft-editor/index.jsx 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/form/simple-form/index.jsx 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/form/step-form/index.jsx 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/form/tab-form/index.jsx 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/group/groupcomponents/index.jsx 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/module/voucher/index.jsx 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/table/base-table/columns/index.jsx 59 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/table/base-table/index.jsx 136 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/table/base-table/index.scss 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/table/base-table/options.jsx 108 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/table/edit-table/index.jsx 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/table/normal-table/index.jsx 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/tabs/antv-tabs/index.scss 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/tabs/tabcomponents/index.jsx 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/tabs/table-tabs/dragabletabs.jsx 129 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/tabs/table-tabs/index.jsx 401 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/tabs/table-tabs/index.scss 144 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/tabs/table-tabs/options.jsx 267 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/timeline/normal-timeline/index.jsx 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/tree/antd-tree/index.jsx 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/menushell/index.jsx 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/picturecontroller/index.jsx 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/picturecontroller/index.scss 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/stylecombcontrolbutton/index.jsx 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/stylecombcontroller/index.jsx 102 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/tableshell/card.jsx 32 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/tableshell/index.jsx 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/urlfieldcomponent/index.scss 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/mob/components/menubar/common-menubar/index.jsx 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/mob/components/menubar/normal-menubar/index.jsx 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/mob/components/navbar/normal-navbar/index.jsx 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/mob/components/tabs/antv-tabs/index.scss 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/mob/components/tabs/tabcomponents/index.jsx 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/mob/mobshell/index.jsx 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pc/components/login/normal-login/index.jsx 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pc/components/navbar/normal-navbar/index.jsx 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pc/menushell/index.jsx 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/group/normal-group/index.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/share/tabtransfer/index.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/index.jsx 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/calendarconfig/source.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/comtableconfig/source.jsx 54 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/actioncomponent/index.jsx 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/tablecomponent/index.jsx 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/tablecomponent/index.scss 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/subtableconfig/source.jsx 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/zshare/formconfig.jsx 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/utils-custom.js 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/billprint/index.jsx 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mobdesign/index.jsx 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/tabledesign/index.jsx 43 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/tabledesign/source.jsx 177 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/tabledesign/tablesource/index.jsx 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/tabledesign/tablesource/index.scss 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/locales/en-US/model.js
@@ -35,7 +35,6 @@
  'model.window': 'Window',
  'model.empty': 'Empty',
  'model.pay': 'Pay',
  'model.operation': 'Action',
  'model.switch.open': 'Open',
  'model.switch.close': 'Close',
  'model.menu.level1': 'Level 1 menu',
src/locales/zh-CN/model.js
@@ -35,7 +35,6 @@
  'model.window': '窗口',
  'model.empty': '空',
  'model.pay': '支付',
  'model.operation': '操作',
  'model.switch.open': '开',
  'model.switch.close': '关',
  'model.menu.level1': '一级菜单',
src/menu/components/card/balcony/index.jsx
@@ -44,7 +44,6 @@
        format: 'object',   // 组件属性 - 数据格式
        pageable: false,    // 组件属性 - 是否可分页
        switchable: false,  // 组件属性 - 数据是否可切换
        dataName: card.dataName || '',
        width: card.width || 24,
        name: card.name,
        subtype: card.subtype,
src/menu/components/card/data-card/index.jsx
@@ -51,7 +51,6 @@
        format: 'array',   // 组件属性 - 数据格式
        pageable: true,    // 组件属性 - 是否可分页
        switchable: true,  // 组件属性 - 数据是否可切换
        dataName: card.dataName || '',
        width: card.width || 24,
        name: card.name,
        subtype: card.subtype,
src/menu/components/card/prop-card/index.jsx
@@ -49,7 +49,6 @@
        format: 'object',   // 组件属性 - 数据格式
        pageable: false,    // 组件属性 - 是否可分页
        switchable: true,  // 组件属性 - 数据是否可切换
        dataName: card.dataName || '',
        width: card.width || 24,
        name: card.name,
        subtype: card.subtype,
src/menu/components/card/table-card/index.jsx
@@ -50,7 +50,6 @@
        format: 'array',    // 组件属性 - 数据格式
        pageable: true,     // 组件属性 - 是否可分页
        switchable: false,  // 组件属性 - 数据是否可切换
        dataName: card.dataName || '',
        width: card.width || 12,
        search: [],
        name: card.name,
src/menu/components/carousel/data-card/index.jsx
@@ -46,7 +46,6 @@
        format: 'array',    // 组件属性 - 数据格式
        pageable: false,    // 组件属性 - 是否可分页
        switchable: false,   // 组件属性 - 数据是否可切换
        dataName: card.dataName || '',
        width: card.width || 24,
        name: card.name,
        subtype: card.subtype,
src/menu/components/carousel/prop-card/index.jsx
@@ -47,7 +47,6 @@
        format: 'object',   // 组件属性 - 数据格式
        pageable: false,    // 组件属性 - 是否可分页
        switchable: false,  // 组件属性 - 数据是否可切换
        dataName: card.dataName || '',
        width: card.width || 24,
        name: card.name,
        subtype: card.subtype,
src/menu/components/chart/antv-bar/index.jsx
@@ -75,7 +75,6 @@
        format: 'array',   // 组件属性 - 数据格式
        pageable: false,   // 组件属性 - 是否可分页
        switchable: card.type === 'bar' ? true : false, // 组件属性 - 数据是否可切换
        dataName: card.dataName || '',
        width: _plot.width,
        name: _plot.name,
        subtype: card.subtype,
src/menu/components/chart/antv-dashboard/index.jsx
@@ -118,7 +118,6 @@
        format: card.subtype === 'ratioboard' ? 'array' : 'object',   // 组件属性 - 数据格式
        pageable: false,    // 组件属性 - 是否可分页
        switchable: false,  // 组件属性 - 数据是否可切换
        dataName: card.dataName || '',
        width: _plot.width,
        name: _plot.name,
        subtype: card.subtype,
src/menu/components/chart/antv-pie/index.jsx
@@ -68,7 +68,6 @@
        format: 'array',   // 组件属性 - 数据格式
        pageable: false,   // 组件属性 - 是否可分页
        switchable: false, // 组件属性 - 数据是否可切换
        dataName: card.dataName || '',
        width: _plot.width,
        name: _plot.name,
        subtype: card.subtype,
src/menu/components/chart/antv-scatter/index.jsx
@@ -62,7 +62,6 @@
        format: 'array',   // 组件属性 - 数据格式
        pageable: false,   // 组件属性 - 是否可分页
        switchable: false, // 组件属性 - 数据是否可切换
        dataName: card.dataName || '',
        width: _plot.width,
        name: _plot.name,
        subtype: card.subtype,
src/menu/components/chart/chart-custom/index.jsx
@@ -55,7 +55,6 @@
        format: 'array',   // 组件属性 - 数据格式
        pageable: false,   // 组件属性 - 是否可分页
        switchable: false, // 组件属性 - 数据是否可切换
        dataName: card.dataName || '',
        width: _plot.width,
        name: _plot.name,
        subtype: card.subtype,
src/menu/components/code/sandbox/index.jsx
@@ -43,7 +43,6 @@
        type: card.type,
        tabId: card.tabId || '',
        parentId: card.parentId || '',
        dataName: card.dataName || '',
        format: 'object',   // 组件属性 - 数据格式
        pageable: false,    // 组件属性 - 是否可分页
        switchable: false,  // 组件属性 - 数据是否可切换
src/menu/components/editor/braft-editor/index.jsx
@@ -41,7 +41,6 @@
        type: card.type,
        tabId: card.tabId || '',
        parentId: card.parentId || '',
        dataName: card.dataName || '',
        format: 'object',   // 组件属性 - 数据格式
        pageable: false,    // 组件属性 - 是否可分页
        switchable: false,  // 组件属性 - 数据是否可切换
src/menu/components/form/simple-form/index.jsx
@@ -63,7 +63,6 @@
        format: 'object',   // 组件属性 - 数据格式
        pageable: false,    // 组件属性 - 是否可分页
        switchable: false,  // 组件属性 - 数据是否可切换
        dataName: card.dataName || '',
        width: card.width || 24,
        name: card.name,
        subtype: card.subtype,
src/menu/components/form/step-form/index.jsx
@@ -64,7 +64,6 @@
        format: 'object',   // 组件属性 - 数据格式
        pageable: false,    // 组件属性 - 是否可分页
        switchable: false,  // 组件属性 - 数据是否可切换
        dataName: card.dataName || '',
        width: card.width || 24,
        name: card.name,
        subtype: card.subtype,
src/menu/components/form/tab-form/index.jsx
@@ -64,7 +64,6 @@
        format: 'object',   // 组件属性 - 数据格式
        pageable: false,    // 组件属性 - 是否可分页
        switchable: false,  // 组件属性 - 数据是否可切换
        dataName: card.dataName || '',
        width: card.width || 24,
        name: card.name,
        subtype: card.subtype,
src/menu/components/group/groupcomponents/index.jsx
@@ -104,7 +104,6 @@
        subtype: item.subtype,
        config: item.config,
        width: item.width || 24,
        dataName: Utils.getdataName(),
        name: name,
        isNew: true               // 新添加标志,用于初始化
      }
src/menu/components/module/voucher/index.jsx
@@ -35,7 +35,6 @@
        type: card.type,
        tabId: card.tabId || '',
        parentId: card.parentId || '',
        dataName: card.dataName || '',
        format: 'array',    // 组件属性 - 数据格式
        pageable: false,    // 组件属性 - 是否可分页
        switchable: false,  // 组件属性 - 数据是否可切换
src/menu/components/table/base-table/columns/index.jsx
@@ -3,7 +3,7 @@
import { is, fromJS } from 'immutable'
import { DndProvider, DragSource, DropTarget } from 'react-dnd'
import { Table, Popover, Modal, message } from 'antd'
import { PlusOutlined, FileSyncOutlined, EditOutlined, CopyOutlined, DeleteOutlined, FontColorsOutlined, CloseCircleOutlined, AntDesignOutlined } from '@ant-design/icons'
import { PlusOutlined, EditOutlined, CopyOutlined, DeleteOutlined, FontColorsOutlined, CloseCircleOutlined, AntDesignOutlined } from '@ant-design/icons'
import asyncComponent from '@/utils/asyncComponent'
import asyncIconComponent from '@/utils/asyncIconComponent'
@@ -501,61 +501,6 @@
    })
  }
  syncfield = () => {
    const { fields } = this.state
    let columns = fromJS(this.state.columns).toJS()
    columns = columns.filter(c => !c.origin)
    let keys = columns.map(col => col.field)
    fields.forEach(item => {
      if (keys.includes(item.field)) return
      let cell = { uuid: Utils.getuuid(), label: item.label, field: item.field, Align: 'left', Hide: 'false', IsSort: 'true', Width: 120, blacklist: [], postfix: '', prefix: '', linkmenu: [], marks: [], perspective: 'linkmenu' }
      if (/Nvarchar|date/ig.test(item.datatype)) {
        cell.type = 'text'
        cell.rowspan = 'false'
        cell.textFormat = 'none'
      } else {
        cell.type = 'number'
        cell.format = 'none'
        cell.sum = 'false'
        cell.decimal = item.decimal || 0
        cell.Width = 80
      }
      columns.push(cell)
    })
    const _this = this
    confirm({
      content: '确定同步字段集吗?',
      onOk() {
        _this.setState({columns}, () => {
          _this.props.updatecolumn({..._this.props.config, cols: columns})
        })
      },
      onCancel() {}
    })
  }
  clear = () => {
    const _this = this
    confirm({
      content: '确定清空显示列吗?',
      onOk() {
        _this.setState({columns: []}, () => {
          _this.props.updatecolumn({..._this.props.config, cols: []})
        })
      },
      onCancel() {}
    })
  }
  /**
   * @description 组件销毁,清除state更新,清除快捷键设置
   */
@@ -584,8 +529,6 @@
        <div className="col-control">
          <CopyOutlined title="复制显示列" onClick={this.copycolumn} />
          <MarkColumn columns={fields} type="line" marks={lineMarks} onSubmit={this.updateLineMarks} />
          <FileSyncOutlined title="同步字段集" onClick={this.syncfield} />
          <DeleteOutlined title="清空显示列" onClick={this.clear}/>
        </div>
        <DndProvider>
          <Table
src/menu/components/table/base-table/index.jsx
@@ -2,11 +2,10 @@
import PropTypes from 'prop-types'
import { is, fromJS } from 'immutable'
import { Popover } from 'antd'
import { PlusOutlined, PlusCircleOutlined, PlusSquareOutlined, EditOutlined, ToolOutlined, DeleteOutlined, FontColorsOutlined } from '@ant-design/icons'
import { EditOutlined, ToolOutlined, FontColorsOutlined } from '@ant-design/icons'
import asyncComponent from '@/utils/asyncComponent'
import asyncIconComponent from '@/utils/asyncIconComponent'
import { resetStyle } from '@/utils/utils-custom.js'
import MKEmitter from '@/utils/events.js'
import getWrapForm from './options'
import Utils from '@/utils/utils.js'
@@ -17,16 +16,13 @@
const NormalForm = asyncIconComponent(() => import('@/components/normalform'))
const SearchComponent = asyncComponent(() => import('@/templates/sharecomponent/searchcomponent'))
const ActionComponent = asyncComponent(() => import('@/menu/components/share/actioncomponent'))
const NormalHeader = asyncComponent(() => import('@/menu/components/share/normalheader'))
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 ColumnComponent = asyncComponent(() => import('./columns'))
class TableCardEditComponent extends Component {
  static propTpyes = {
    card: PropTypes.object,
    deletecomponent: PropTypes.func,
    updateConfig: PropTypes.func,
  }
@@ -47,21 +43,18 @@
        format: 'array',    // 组件属性 - 数据格式
        pageable: true,     // 组件属性 - 是否可分页
        switchable: true,   // 组件属性 - 数据是否可切换
        dataName: Utils.getdataName(),
        width: 24,
        search: [
          { origin: true, uuid: Utils.getuuid(), label: 'label', field: '', type: 'text', match: 'like' },
          { origin: true, uuid: Utils.getuuid(), label: 'label', field: '', type: 'select', match: 'equal' }
          { origin: true, uuid: Utils.getuuid(), label: 'label', field: '', type: 'select', match: '=' }
        ],
        action: [
          { origin: true, uuid: Utils.getuuid(), label: '添加', intertype: 'system', OpenType: 'pop', execSuccess: 'grid', icon: 'plus', class: 'green', style: {color: 'rgb(255, 255, 255)', background: 'rgb(38, 194, 129)', marginRight: '15px'} },
          { origin: true, uuid: Utils.getuuid(), label: '修改', intertype: 'system', OpenType: 'pop', execSuccess: 'grid', icon: 'form', class: 'purple', style: {color: 'rgb(255, 255, 255)', background: 'rgb(142, 68, 173)', marginRight: '15px'} },
          { origin: true, uuid: Utils.getuuid(), label: '删除', intertype: 'system', OpenType: 'prompt', execSuccess: 'grid', Ot: 'required', icon: 'delete', class: 'danger', style: {color: 'rgb(255, 255, 255)', background: 'rgb(255, 77, 79)', marginRight: '15px'} }
        ],
        name: card.name,
        subtype: card.subtype,
        setting: { interType: 'system' },
        wrap: { name: card.name, width: 24, bordered: 'true', tableType: 'checkbox', show: 'true' },
        wrap: { bordered: 'true', tableType: 'checkbox', show: 'true' },
        style: { marginLeft: '8px', marginRight: '8px', marginTop: '8px', marginBottom: '8px' },
        headerStyle: { fontSize: '16px', borderBottomWidth: '1px', borderBottomColor: '#e8e8e8' },
        columns: [],
@@ -72,52 +65,6 @@
        ],
        scripts: [],
        isNew: true
      }
      if (card.config) {
        let config = fromJS(card.config).toJS()
        _card.wrap = config.wrap
        _card.wrap.name = card.name
        _card.style = config.style
        _card.headerStyle = config.headerStyle
        _card.setting = config.setting
        _card.columns = config.columns
        _card.scripts = config.scripts
        let oriUids = {}
        _card.action = config.action.map(item => {
          let _uuid = Utils.getuuid()
          oriUids[item.uuid] = _uuid
          item.uuid = _uuid
          return item
        })
        _card.search = config.search.map(item => {
          item.uuid = Utils.getuuid()
          return item
        })
        _card.cols = config.cols.map(col => {
          col.uuid = Utils.getuuid()
          if (col.type === 'colspan' && col.subcols) {
            col = this.loopCol(col)
          } else if (col.type === 'custom' && col.elements) {
            col.elements = col.elements.map(cell => {
              cell.uuid = Utils.getuuid()
              return cell
            })
          } else if (col.type === 'action' && col.elements) {
            col.elements = col.elements.map(cell => {
              cell.uuid = Utils.getuuid()
              return cell
            })
          }
          return col
        })
        if (_card.wrap.doubleClick) {
          _card.wrap.doubleClick = oriUids[_card.wrap.doubleClick] || ''
        }
      }
      this.updateComponent(_card)
@@ -186,9 +133,6 @@
   * @description 卡片行外层信息更新(数据源,样式等)
   */
  updateComponent = (card) => {
    card.width = card.wrap.width
    card.name = card.wrap.name
    if (!window.GLOB.styling || !card.errors) { // 样式修改时不做筛查
      card.errors = []
@@ -271,7 +215,7 @@
    style.fontSize = card.wrap.fontSize || 14
    style.fontWeight = card.wrap.fontWeight || 'normal'
    MKEmitter.emit('changeStyle', ['font1', 'background', 'border', 'padding', 'margin', 'shadow'], style, this.getStyle)
    MKEmitter.emit('changeStyle', ['font1', 'padding', 'margin'], style, this.getStyle)
  }
  getStyle = (style) => {
@@ -294,48 +238,6 @@
    _card.wrap.fontWeight = fontWeight
    this.updateComponent(_card)
  }
  addColumns = () => {
    let card = fromJS(this.state.card).toJS()
    card.cols.push({ focus: true, uuid: Utils.getuuid(), label: 'label', field: '', type: 'text' })
    this.setState({card})
  }
  addSearch = () => {
    const { card } = this.state
    MKEmitter.emit('plusSearch', card.uuid, {uuid: Utils.getuuid(), focus: true, label: 'label', type: 'text', match: '='}, 'simple')
  }
  addButton = () => {
    const { card } = this.state
    let newcard = {}
    newcard.uuid = Utils.getuuid()
    newcard.focus = true
    newcard.label = 'label'
    newcard.sqlType = ''
    newcard.Ot = 'requiredSgl'
    newcard.OpenType = 'pop'
    newcard.icon = ''
    newcard.class = 'green'
    newcard.intertype = card.setting.interType || 'system'
    newcard.innerFunc = card.setting.innerFunc || ''
    newcard.sysInterface = card.setting.sysInterface || ''
    newcard.outerFunc = card.setting.outerFunc || ''
    newcard.interface = card.setting.interface || ''
    newcard.execSuccess = 'grid'
    newcard.execError = 'never'
    newcard.verify = null
    newcard.show = 'button'
    newcard.style = {marginRight: '15px'}
    // 注册事件-添加按钮
    MKEmitter.emit('addButton', card.uuid, newcard)
  }
  setSubConfig = (item) => {
@@ -407,34 +309,20 @@
    this.updateComponent({...card, wrap: res})
  }
  clickComponent = (e) => {
    if (sessionStorage.getItem('style-control') === 'true' || sessionStorage.getItem('style-control') === 'component') {
      e.stopPropagation()
      MKEmitter.emit('clickComponent', this.state.card)
    }
  }
  render() {
    const { card } = this.state
    let options = ['action', 'search', 'form', 'cols']
    let _style = resetStyle(card.style)
    return (
      <div className="menu-normal-table-edit-box" style={_style} onClick={this.clickComponent} id={card.uuid}>
        <NormalHeader hideSearch="true" config={card} updateComponent={this.updateComponent}/>
      <div className="menu-base-table-edit-box" style={card.style} id={card.uuid}>
        <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={
          <div className="mk-popover-control">
            <PlusOutlined className="plus" title="添加列" onClick={this.addColumns}/>
            <PlusCircleOutlined className="plus" title="添加搜索" onClick={this.addSearch}/>
            <PlusSquareOutlined className="plus" title="添加按钮" onClick={this.addButton}/>
            <NormalForm title="表格设置" width={800} update={this.updateWrap} getForms={this.getWrapForms}>
              <EditOutlined style={{color: '#1890ff'}} title="编辑"/>
            </NormalForm>
            <CopyComponent type="normaltable" card={card}/>
            <PasteComponent config={card} options={options} updateConfig={this.updateComponent} />
            <FontColorsOutlined className="style" title="调整样式" onClick={this.changeStyle}/>
            <UserComponent config={card}/>
            <DeleteOutlined className="close" title="删除组件" onClick={() => this.props.deletecomponent(card.uuid)} />
            <SettingComponent config={card} updateConfig={this.updateComponent} />
          </div>
        } trigger="hover">
@@ -443,20 +331,6 @@
        <SearchComponent config={card} updatesearch={this.updateComponent}/>
        <ActionComponent config={card} setSubConfig={this.setSubConfig} updateaction={this.updateComponent}/>
        <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/base-table/index.scss
@@ -1,4 +1,4 @@
.menu-normal-table-edit-box {
.menu-base-table-edit-box {
  position: relative;
  box-sizing: border-box;
  background: #ffffff;
@@ -80,13 +80,4 @@
  .ant-btn.mk-link {
    padding: 0;
  }
}
.menu-normal-table-edit-box::after {
  display: block;
  content: ' ';
  clear: both;
}
.menu-normal-table-edit-box:hover {
  z-index: 1;
  box-shadow: 0px 0px 4px #1890ff;
}
src/menu/components/table/base-table/options.jsx
@@ -16,36 +16,36 @@
  }
  const wrapForm = [
    {
      type: 'text',
      field: 'title',
      label: '标题',
      initval: wrap.title || '',
      required: false
    },
    {
      type: 'text',
      field: 'name',
      label: '组件名称',
      initval: wrap.name || '',
      tooltip: '用于组件间的区分。',
      required: true
    },
    {
      type: 'number',
      field: 'width',
      label: '宽度',
      initval: wrap.width || 24,
      tooltip: '栅格布局,每行等分为24列。',
      min: 1,
      max: 24,
      precision: 0,
      required: true
    },
    // {
    //   type: 'text',
    //   field: 'title',
    //   label: '标题',
    //   initval: wrap.title || '',
    //   required: false
    // },
    // {
    //   type: 'text',
    //   field: 'name',
    //   label: '组件名称',
    //   initval: wrap.name || '',
    //   tooltip: '用于组件间的区分。',
    //   required: true
    // },
    // {
    //   type: 'number',
    //   field: 'width',
    //   label: '宽度',
    //   initval: wrap.width || 24,
    //   tooltip: '栅格布局,每行等分为24列。',
    //   min: 1,
    //   max: 24,
    //   precision: 0,
    //   required: true
    // },
    {
      type: 'number',
      field: 'height',
      label: '高度',
      label: '表格高度',
      initval: wrap.height || '',
      tooltip: '表格高度,空值时高度自适应。',
      min: 10,
@@ -141,18 +141,18 @@
        {value: 'always', label: '数据加载'},
      ]
    },
    // {
    //   type: 'radio',
    //   field: 'show',
    //   label: '搜索按钮',
    //   initval: wrap.show || 'true',
    //   tooltip: '搜索条件存在时,可选择是否显示搜索按钮。',
    //   required: false,
    //   options: [
    //     {value: 'true', label: '显示'},
    //     {value: 'false', label: '隐藏'},
    //   ]
    // },
    {
      type: 'radio',
      field: 'mask',
      label: '遮罩',
      initval: wrap.mask || 'show',
      tooltip: '数据加载时,是否显示加载中的遮罩。',
      required: false,
      options: [
        {value: 'show', label: '显示'},
        {value: 'hidden', label: '隐藏'},
      ]
    },
    {
      type: 'color',
      field: 'borderColor',
@@ -161,36 +161,6 @@
      tooltip: '默认值 #e8e8e8。',
      required: false
    },
    // {
    //   type: 'color',
    //   field: 'color',
    //   label: '字体颜色',
    //   initval: wrap.color || 'rgba(0, 0, 0, 0.65)',
    //   tooltip: '默认值 rgba(0, 0, 0, 0.65)。',
    //   required: false
    // },
    // {
    //   type: 'number',
    //   field: 'fontSize',
    //   label: '字体大小',
    //   initval: wrap.fontSize || 14,
    //   min: 12,
    //   max: 30,
    //   precision: 0,
    //   required: false
    // },
    // {
    //   type: 'number',
    //   field: 'advanceWidth',
    //   label: '高级搜索',
    //   initval: wrap.advanceWidth || 1000,
    //   tooltip: '高级搜索弹窗的宽度,注:当宽度值小于100时表示占窗口的百分比,大于100时表示宽度的绝对值。',
    //   min: 10,
    //   max: 3000,
    //   precision: 0,
    //   required: false,
    //   forbid: appType === 'mob'
    // },
    {
      type: 'select',
      field: 'doubleClick',
src/menu/components/table/edit-table/index.jsx
@@ -51,7 +51,6 @@
        format: 'array',    // 组件属性 - 数据格式
        pageable: true,     // 组件属性 - 是否可分页
        switchable: false,  // 组件属性 - 数据是否可切换
        dataName: card.dataName || '',
        width: card.width || 24,
        search: [],
        action: [],
src/menu/components/table/normal-table/index.jsx
@@ -50,11 +50,10 @@
        format: 'array',    // 组件属性 - 数据格式
        pageable: true,     // 组件属性 - 是否可分页
        switchable: true,   // 组件属性 - 数据是否可切换
        dataName: card.dataName || '',
        width: card.width || 24,
        search: [
          { origin: true, uuid: Utils.getuuid(), label: 'label', field: '', type: 'text', match: 'like' },
          { origin: true, uuid: Utils.getuuid(), label: 'label', field: '', type: 'select', match: 'equal' }
          { origin: true, uuid: Utils.getuuid(), label: 'label', field: '', type: 'select', match: '=' }
        ],
        action: [
          { origin: true, uuid: Utils.getuuid(), label: '添加', intertype: 'system', OpenType: 'pop', execSuccess: 'grid', icon: 'plus', class: 'green', style: {color: 'rgb(255, 255, 255)', background: 'rgb(38, 194, 129)', marginRight: '15px'} },
src/menu/components/tabs/antv-tabs/index.scss
@@ -49,6 +49,7 @@
  }
  .ant-tabs .ant-tabs-top-bar > .ant-tabs-nav-container {
    min-height: 40px;
    >.ant-tabs-tab-next:not(.ant-tabs-tab-arrow-show) + .ant-tabs-nav-wrap > .ant-tabs-nav-scroll > .ant-tabs-nav {
      width: 100%;
      > div > .ant-tabs-tab-disabled {
src/menu/components/tabs/tabcomponents/index.jsx
@@ -135,7 +135,6 @@
        subtype: item.subtype,
        config: item.config,
        width: item.width || 24,
        dataName: Utils.getdataName(),
        name: name,
        isNew: true                                   // 新添加标志,用于初始化
      }
src/menu/components/tabs/table-tabs/dragabletabs.jsx
New file
@@ -0,0 +1,129 @@
import React, { Component } from 'react'
import { Tabs } from 'antd'
import { is, fromJS } from 'immutable'
import { DndProvider, DragSource, DropTarget } from 'react-dnd'
// Drag & Drop node
class TabNode extends Component {
  render() {
    const { connectDragSource, connectDropTarget, children } = this.props
    return connectDragSource(connectDropTarget(children))
  }
}
const cardTarget = {
  drop(props, monitor) {
    const dragKey = monitor.getItem().index
    const hoverKey = props.index
    if (dragKey === hoverKey) {
      return;
    }
    props.moveTabNode(dragKey, hoverKey)
    monitor.getItem().index = hoverKey
  }
}
const cardSource = {
  beginDrag(props) {
    return {
      id: props.id,
      index: props.index,
    }
  }
}
const WrapTabNode = DropTarget('DND_NODE', cardTarget, connect => ({
  connectDropTarget: connect.dropTarget(),
}))(
  DragSource('DND_NODE', cardSource, (connect, monitor) => ({
    connectDragSource: connect.dragSource(),
    isDragging: monitor.isDragging(),
  }))(TabNode)
)
class DraggableTabs extends Component {
  state = {
    order: []
  }
  moveTabNode = (dragKey, hoverKey) => {
    const newOrder = this.state.order.slice()
    const { children } = this.props
    React.Children.forEach(children, c => {
      if (newOrder.indexOf(c.key) === -1) {
        newOrder.push(c.key)
      }
    })
    const dragIndex = newOrder.indexOf(dragKey)
    const hoverIndex = newOrder.indexOf(hoverKey)
    newOrder.splice(dragIndex, 1)
    newOrder.splice(hoverIndex, 0, dragKey)
    this.setState({
      order: newOrder
    })
    this.props.tabsMove(newOrder)
  }
  renderTabBar = (props, DefaultTabBar) => (
    <DefaultTabBar {...props}>
      {node => (
        <WrapTabNode key={node.key} index={node.key} moveTabNode={this.moveTabNode}>
          {node}
        </WrapTabNode>
      )}
    </DefaultTabBar>
  )
  shouldComponentUpdate (nextProps, nextState) {
    return !is(fromJS(this.state), fromJS(nextState)) ||
      !is(fromJS(nextProps.children), fromJS(this.props.children)) ||
      nextProps.tabPosition !== this.props.tabPosition ||
      nextProps.type !== this.props.type
  }
  render() {
    const { order } = this.state
    const { children, ...resProps } = this.props
    const tabs = []
    React.Children.forEach(children, c => {
      tabs.push(c)
    })
    const orderTabs = tabs.slice().sort((a, b) => {
      const orderA = order.indexOf(a.key)
      const orderB = order.indexOf(b.key)
      if (orderA !== -1 && orderB !== -1) {
        return orderA - orderB
      }
      if (orderA !== -1) {
        return -1
      }
      if (orderB !== -1) {
        return 1
      }
      const ia = tabs.indexOf(a)
      const ib = tabs.indexOf(b)
      return ia - ib
    })
    return (
      <DndProvider>
        <Tabs renderTabBar={this.renderTabBar} {...resProps}>
          {orderTabs}
        </Tabs>
      </DndProvider>
    )
  }
}
export default DraggableTabs
src/menu/components/tabs/table-tabs/index.jsx
New file
@@ -0,0 +1,401 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import { is, fromJS } from 'immutable'
import { Tabs, Popover, Modal } from 'antd'
import { PlusOutlined, CloseOutlined, EditOutlined, DeleteOutlined, FontColorsOutlined, ToolOutlined } from '@ant-design/icons'
import MKEmitter from '@/utils/events.js'
import asyncComponent from '@/utils/asyncComponent'
import asyncIconComponent from '@/utils/asyncIconComponent'
import MkIcon from '@/components/mk-icon'
import DraggableTabs from './dragabletabs'
import { resetStyle } from '@/utils/utils-custom.js'
import MenuUtils from '@/utils/utils-custom.js'
import Utils from '@/utils/utils.js'
import { getTabForm, getTabsSetForm } from './options'
import './index.scss'
const NormalForm = asyncIconComponent(() => import('@/components/normalform'))
const CopyComponent = asyncIconComponent(() => import('@/menu/components/share/copycomponent'))
const PasteComponent = asyncIconComponent(() => import('../paste'))
const TabComponents = asyncComponent(() => import('../tabcomponents'))
const { TabPane } = Tabs
const { confirm } = Modal
class antvTabs extends Component {
  static propTpyes = {
    tabs: PropTypes.object,
    deletecomponent: PropTypes.func,
    updateConfig: PropTypes.func,
  }
  state = {
    appType: sessionStorage.getItem('appType'),
    tabs: null,
    editab: null,
    defaultActiveKey: ''
  }
  UNSAFE_componentWillMount () {
    const { tabs } = this.props
    if (tabs.isNew) {
      let _tabs = {
        uuid: tabs.uuid,
        type: tabs.type,
        tabId: tabs.tabId || '',
        parentId: tabs.parentId || '',
        subtype: tabs.subtype,
        width: 24,
        name: tabs.name,
        setting: {width: 24, position: 'top', tabStyle: 'line', name: tabs.name},
        style: { marginLeft: '8px', marginRight: '8px', marginTop: '8px', marginBottom: '8px' },
        subtabs: [
          { uuid: Utils.getuuid(), parentId: tabs.uuid, label: 'Tab 1', icon: '', components: [] },
          { uuid: Utils.getuuid(), parentId: tabs.uuid, label: 'Tab 2', icon: '', components: [] },
          { uuid: Utils.getuuid(), parentId: tabs.uuid, label: 'Tab 3', icon: '', components: [] }
        ]
      }
      this.setState({
        defaultActiveKey: _tabs.subtabs[0].uuid,
        tabs: _tabs
      })
      this.props.updateConfig(_tabs)
    } else {
      this.setState({
        defaultActiveKey: window.GLOB.TabsMap.get(tabs.uuid) || '',
        tabs: fromJS(tabs).toJS()
      })
    }
  }
  shouldComponentUpdate (nextProps, nextState) {
    return !is(fromJS(this.state), fromJS(nextState))
  }
  componentDidMount () {
    MKEmitter.addListener('submitSearch', this.getSearch)
    MKEmitter.addListener('tabsChange', this.handleTabsChange)
    MKEmitter.addListener('submitComponentStyle', this.updateComponentStyle)
  }
  /**
   * @description 组件销毁,清除state更新,清除快捷键设置
   */
  componentWillUnmount () {
    this.setState = () => {
      return
    }
    MKEmitter.removeListener('submitSearch', this.getSearch)
    MKEmitter.removeListener('tabsChange', this.handleTabsChange)
    MKEmitter.removeListener('submitComponentStyle', this.updateComponentStyle)
  }
  updateComponentStyle = (parentId, keys, style) => {
    const { tabs } = this.state
    if (tabs.subtabs.findIndex(tab => tab.uuid === parentId) === -1) return
    let _tabs = fromJS(tabs).toJS()
    let _tabs_ = fromJS(tabs).toJS()
    let components = []
    _tabs.subtabs.forEach(tab => {
      if (tab.uuid === parentId) {
        components = tab.components.map(item => {
          if (keys.includes(item.uuid)) {
            item.style = {...item.style, ...style}
          }
          return item
        })
        tab.components = []
      }
    })
    _tabs_.subtabs = _tabs_.subtabs.map(tab => {
      if (tab.uuid === parentId) {
        tab.components = components
      }
      return tab
    })
    this.setState({tabs: _tabs}, () => {
      this.updateComponent(_tabs_)
    })
  }
  changeStyle = () => {
    const { tabs } = this.state
    MKEmitter.emit('changeStyle', ['background', 'border', 'padding', 'margin', 'shadow'], tabs.style, this.getStyle)
  }
  getStyle = (style) => {
    let _card = {...this.state.tabs, style}
    this.setState({
      tabs: _card
    })
    this.props.updateConfig(_card)
  }
  handleTabsChange = (parentId) => {
    const { tabs } = this.state
    if (parentId === tabs.parentId) {
      MKEmitter.emit('tabsChange', tabs.uuid)
    }
  }
  updateComponent = (component) => {
    const { tabs } = this.state
    if (!is(fromJS(tabs.setting), fromJS(component.setting)) || !is(fromJS(tabs.style), fromJS(component.style))) {
      // 注册事件-标签变化,通知标签内元素
      MKEmitter.emit('tabsChange', tabs.uuid)
    }
    component.width = component.setting.width
    component.name = component.setting.name
    this.setState({
      tabs: component
    })
    this.props.updateConfig(component)
  }
  updateTabComponent = (tab) => {
    let tabs = fromJS(this.state.tabs).toJS()
    tabs.subtabs = tabs.subtabs.map(t => {
      if (t.uuid === tab.uuid) {
        return tab
      } else {
        return t
      }
    })
    this.setState({tabs})
    this.props.updateConfig(tabs)
  }
  delTab = (tab) => {
    let tabs = fromJS(this.state.tabs).toJS()
    const _this = this
    tabs.subtabs = tabs.subtabs.filter(t => t.uuid !== tab.uuid)
    let uuids = MenuUtils.getDelButtonIds({...tab, type: 'group'})
    confirm({
      title: '确定删除标签?',
      content: '',
      onOk() {
        _this.setState({tabs})
        _this.props.updateConfig(tabs)
        if (uuids.length === 0) return
        MKEmitter.emit('delButtons', uuids)
      },
      onCancel() {}
    })
  }
  moveSwitch = (order) => {
    let tabs = fromJS(this.state.tabs).toJS()
    let subtab = {}
    tabs.subtabs.forEach(item => {
      subtab[item.uuid] = item
    })
    tabs.subtabs = []
    order.forEach(item => {
      if (subtab[item]) {
        tabs.subtabs.push(subtab[item])
      }
    })
    this.setState({tabs})
    this.props.updateConfig(tabs)
  }
  insert = (item, tab) => {
    let tabs = fromJS(this.state.tabs).toJS()
    tabs.subtabs.forEach(stab => {
      if (stab.uuid === tab.uuid) {
        stab.components.push(item)
      }
    })
    this.setState({tabs})
    this.props.updateConfig(tabs)
  }
  getSearch = (config) => {
    const { tabs } = this.state
    if (tabs.uuid !== config.uuid) return
    let _tabs = fromJS(tabs).toJS()
    _tabs.subtabs = _tabs.subtabs.map(t => {
      if (t.uuid === config.tabId) {
        t.search = config.search
      }
      return t
    })
    this.setState({
      tabs: _tabs
    })
    this.props.updateConfig(_tabs)
  }
  setSearch = (tab) => {
    const { tabs } = this.state
    let card = {
      uuid: tabs.uuid,
      tabId: tab.uuid,
      search: tab.search
    }
    if (!card.search) {
      card.search = {
        floor: 1,
        setting: { type: 'title', field: '', title: '', focus: 'true', btn: 'hidden' },
        groups: [],
        fields: []
      }
    }
    MKEmitter.emit('changeSearch', card)
  }
  clickComponent = (e) => {
    if (sessionStorage.getItem('style-control') === 'true' || sessionStorage.getItem('style-control') === 'component') {
      e.stopPropagation()
      MKEmitter.emit('clickComponent', this.state.tabs)
    }
  }
  getTabForms = (tab) => {
    const { tabs } = this.state
    if (!tab) {
      tab = {
        uuid: '',
        parentId: tabs.uuid,
        label: '',
        icon: '',
        components: []
      }
    }
    this.setState({
      editab: tab
    })
    return getTabForm(tab, tabs.setting)
  }
  updateTab = (res) => {
    let tabs = fromJS(this.state.tabs).toJS()
    let editab = fromJS(this.state.editab).toJS()
    editab.label = res.label
    editab.icon = res.icon
    // editab.hasSearch = res.hasSearch || ''
    editab.hide = res.hide || 'false'
    editab.backgroundColor = res.backgroundColor
    editab.controlVal = res.controlVal || ''
    editab.selectVal = res.selectVal || ''
    editab.blacklist = res.blacklist
    if (editab.uuid) {
      tabs.subtabs = tabs.subtabs.map(t => {
        if (t.uuid === editab.uuid) {
          return editab
        } else {
          return t
        }
      })
    } else {
      editab.uuid = Utils.getuuid()
      tabs.subtabs.push(editab)
    }
    this.setState({
      editab: null,
      tabs
    })
    this.props.updateConfig(tabs)
  }
  getTabsForms = () => {
    const { tabs } = this.state
    return getTabsSetForm(tabs.setting, tabs.uuid)
  }
  updateTabs = (res) => {
    this.updateComponent({...this.state.tabs, setting: res})
  }
  onChange = (key) => {
    const { tabs } = this.state
    window.GLOB.TabsMap.set(tabs.uuid, key)
  }
  render() {
    const { tabs, defaultActiveKey } = this.state
    let _style = resetStyle(tabs.style)
    return (
      <div className={'menu-tabs-edit-box ' + (tabs.setting.display || '')} style={_style} onClick={this.clickComponent} id={tabs.uuid}>
        <DraggableTabs defaultActiveKey={defaultActiveKey} tabBarStyle={{background: tabs.setting.backgroundColor || 'transparent'}} tabPosition={tabs.setting.position} type={tabs.setting.tabStyle} tabsMove={this.moveSwitch} onChange={this.onChange}>
          {tabs.subtabs.map(tab => (
            <TabPane tab={
              <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={
                <div className="mk-popover-control">
                  <NormalForm title="标签编辑" width={800} update={this.updateTab} getForms={() => this.getTabForms(tab)}>
                    <EditOutlined style={{color: '#1890ff'}} title="编辑"/>
                  </NormalForm>
                  <PasteComponent Tab={tab} insert={this.insert} />
                  <CloseOutlined className="close" onClick={() => this.delTab(tab)} />
                </div>
              } trigger="hover">
                <span style={{textDecoration: tab.hide === 'true' ? 'line-through' : 'none'}}>{tab.icon ? <MkIcon type={tab.icon} /> : null}{tab.label}</span>
              </Popover>
            } key={tab.uuid} style={{backgroundColor: tab.backgroundColor || 'transparent'}}>
              {/* {appType === 'mob' && tabs.setting.position === 'top' && tabs.setting.display === 'inline-block' && tab.hasSearch === 'icon' ?
                <SearchOutlined className="search-icon" onDoubleClick={() => this.setSearch(tab)}/> : null} */}
              <TabComponents config={tab} handleList={this.updateTabComponent} deleteCard={this.deleteCard} />
            </TabPane>
          ))}
        </DraggableTabs>
        <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={
          <div className="mk-popover-control">
            <NormalForm title="添加标签" width={800} update={this.updateTab} getForms={() => this.getTabForms()}>
              <PlusOutlined className="plus" title="添加标签"/>
            </NormalForm>
            <NormalForm title="标签页设置" width={800} update={this.updateTabs} getForms={this.getTabsForms}>
              <EditOutlined style={{color: '#1890ff'}} title="编辑"/>
            </NormalForm>
            <CopyComponent type="tabs" card={tabs}/>
            <FontColorsOutlined className="style" title="调整样式" onClick={this.changeStyle}/>
            <DeleteOutlined className="close" onClick={() => this.props.deletecomponent(tabs.uuid)} />
          </div>
        } trigger="hover">
          <ToolOutlined />
        </Popover>
      </div>
    )
  }
}
export default antvTabs
src/menu/components/tabs/table-tabs/index.scss
New file
@@ -0,0 +1,144 @@
.menu-tabs-edit-box {
  position: relative;
  box-sizing: border-box;
  background: #ffffff;
  background-position: center center;
  background-repeat: no-repeat;
  background-size: cover;
  .ant-tabs-top-bar {
    margin-bottom: 0;
  }
  .ant-tabs-top-content {
    .tab-shell-inner {
      padding-top: 15px;
    }
  }
  .ant-tabs-left-content {
    padding-left: 0;
  }
  .ant-tabs-right-content {
    padding-right: 0;
  }
  .ant-tabs-bottom-bar {
    margin-top: 0;
  }
  >.anticon-tool {
    position: absolute;
    z-index: 2;
    font-size: 16px;
    right: 1px;
    top: 1px;
    cursor: pointer;
    padding: 5px;
    background: rgba(255, 255, 255, 0.55);
  }
  .ant-tabs.ant-tabs-left, .ant-tabs.ant-tabs-bottom {
    .tab-shell-inner {
      padding-top: 25px;
    }
  }
  .ant-tabs-tabpane-active {
    min-height: 200px;
  }
  .tab-shell-inner {
    min-height: 100%;
  }
  .ant-tabs .ant-tabs-top-bar > .ant-tabs-nav-container {
    min-height: 40px;
    >.ant-tabs-tab-next:not(.ant-tabs-tab-arrow-show) + .ant-tabs-nav-wrap > .ant-tabs-nav-scroll > .ant-tabs-nav {
      width: 100%;
      > div > .ant-tabs-tab-disabled {
        float: right;
      }
    }
  }
  .ant-tabs .ant-tabs-left-bar .ant-tabs-tab {
    text-align: right;
    > span {
      display: inline-block;
      padding: 8px 24px;
    }
  }
  .ant-tabs .ant-tabs-right-bar .ant-tabs-tab {
    text-align: left;
    > span {
      display: inline-block;
      padding: 8px 24px;
    }
  }
  .ant-tabs-tab {
    padding: 0px!important;
    text-align: center;
    > span {
      display: inline-block;
      padding: 12px 16px;
    }
  }
  .ant-tabs-bottom .ant-tabs-bottom-bar .ant-tabs-ink-bar {
    top: 0px;
  }
  .ant-tabs-card {
    .ant-tabs-left-bar, .ant-tabs-right-bar {
      .ant-tabs-tab {
        > span {
          padding: 0px 16px;
        }
      }
      .ant-tabs-tab-active {
        padding-left: 0px!important;
        padding-right: 0px!important;
      }
    }
    .ant-tabs-card-bar {
      .ant-tabs-tab {
        > span {
          display: inline-block;
          padding: 0px 16px;
        }
      }
    }
  }
  .search-icon {
    position: absolute;
    top: 10px;
    right: 40px;
    font-size: 18px;
    cursor: pointer;
    padding: 3px;
  }
}
.menu-tabs-edit-box:hover {
  z-index: 1;
  box-shadow: 0px 0px 4px #1890ff;
}
.mob-shell {
  .menu-tabs-edit-box.flex {
    >.ant-tabs.ant-tabs-top, >.ant-tabs.ant-tabs-bottom {
      >.ant-tabs-bar {
        >.ant-tabs-nav-container {
          >.ant-tabs-nav-wrap {
            >.ant-tabs-nav-scroll {
              >.ant-tabs-nav {
                display: block;
                >div {
                  display: flex;
                  >.ant-tabs-tab {
                    flex: 1;
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}
src/menu/components/tabs/table-tabs/options.jsx
New file
@@ -0,0 +1,267 @@
import MenuUtils from '@/utils/utils-custom.js'
/**
 * @description tab表单配置信息
 */
export function getTabForm(tab, setting) {
  let appType = sessionStorage.getItem('appType')
  let roleList = sessionStorage.getItem('sysRoles')
  if (roleList) {
    try {
      roleList = JSON.parse(roleList)
    } catch (e) {
      roleList = []
    }
  } else {
    roleList = []
  }
  const tabForm = [
    {
      type: 'text',
      field: 'label',
      label: '名称',
      initval: tab.label || '',
      required: true,
      focus: true,
    },
    {
      type: 'mkicon',
      field: 'icon',
      label: '图标',
      initval: tab.icon || '',
      required: false,
      allowClear: true,
    },
    // {
    //   type: 'radio',
    //   field: 'hasSearch',
    //   label: '搜索',
    //   initval: tab.hasSearch || 'false',
    //   required: false,
    //   options: [
    //     {value: 'false', label: '无'},
    //     {value: 'icon', label: '有'},
    //   ],
    //   forbid: appType !== 'mob' || setting.position !== 'top' || setting.display !== 'inline-block',
    //   span: 22
    // },
    {
      type: 'text',
      field: 'controlVal',
      label: '隐藏标记',
      initval: tab.controlVal || '',
      tooltip: '当禁用字段值与隐藏标记相等时,标签页会隐藏。注:多个值请用逗号分隔。',
      required: false,
    },
    {
      type: 'text',
      field: 'selectVal',
      label: '选中标记',
      initval: tab.selectVal || '',
      tooltip: '当选中字段值与选中标记相等时,标签页默认选中。',
      required: false
    },
    {
      type: 'color',
      field: 'backgroundColor',
      label: '背景(内容区)',
      initval: tab.backgroundColor || 'transparent',
      required: false,
    },
    {
      type: 'radio',
      field: 'hide',
      label: '隐藏',
      initval: tab.hide || 'false',
      required: false,
      options: [
        {value: 'false', label: '否'},
        {value: 'true', label: '是'},
      ],
    },
    {
      type: 'multiselect',
      field: 'blacklist',
      label: '黑名单',
      initval: tab.blacklist || [],
      required: false,
      options: roleList,
      forbid: !!appType,
    },
  ]
  return tabForm
}
/**
 * @description tabs表单配置信息
 */
export function getTabsSetForm(setting, uuid) {
  let appType = sessionStorage.getItem('appType')
  let roleList = sessionStorage.getItem('sysRoles')
  let modules = MenuUtils.getSupModules(window.GLOB.customMenu.components, uuid) || []
  modules.push({
    value: 'preview',
    label: '上一页(url参数)'
  })
  if (roleList) {
    try {
      roleList = JSON.parse(roleList)
    } catch (e) {
      roleList = []
    }
  } else {
    roleList = []
  }
  const tabForm = [
    {
      type: 'text',
      field: 'name',
      label: '组件名称',
      initval: setting.name || '',
      tooltip: '用于组件间的区分。',
      required: true
    },
    {
      type: 'number',
      field: 'width',
      label: '宽度',
      initval: setting.width || 24,
      tooltip: '栅格布局,每行等分为24列。',
      min: 1,
      max: 24,
      precision: 0,
      required: true
    },
    {
      type: 'select',
      field: 'position',
      label: '标签位置',
      initval: setting.position || 'top',
      required: true,
      options: [
        {value: 'top', label: 'top'},
        {value: 'bottom', label: 'bottom'},
        {value: 'left', label: 'left'},
        {value: 'right', label: 'right'},
      ],
      controlFields: [
        {field: 'display', values: ['top', 'bottom']},
      ]
    },
    {
      type: 'radio',
      field: 'tabStyle',
      label: '页签样式',
      initval: setting.tabStyle || 'line',
      tooltip: '标签位置为top时有效,默认值为line。',
      required: true,
      options: [
        {value: 'line', label: 'line'},
        {value: 'card', label: 'card'},
      ],
    },
    {
      type: 'radio',
      field: 'autoSwitch',
      label: '自动切换',
      initval: setting.autoSwitch || 'false',
      tooltip: '存在两个及以上标签时有效。',
      required: false,
      options: [
        {value: 'true', label: '是'},
        {value: 'false', label: '否'},
      ],
      controlFields: [
        {field: 'interval', values: ['true']},
        {field: 'tabLabel', values: ['true']},
      ]
    },
    {
      type: 'number',
      field: 'interval',
      label: '间隔(s)',
      initval: setting.interval || 5,
      min: 1,
      max: 1000,
      precision: 0,
      required: true
    },
    {
      type: 'radio',
      field: 'tabLabel',
      label: '标签栏',
      initval: setting.tabLabel || 'show',
      required: false,
      options: [
        {value: 'show', label: '显示'},
        {value: 'hide', label: '隐藏'},
      ]
    },
    {
      type: 'cascader',
      field: 'supModule',
      label: '上级组件',
      initval: setting.supModule || [],
      tooltip: '标签组可以选择上级组件,填入禁用字段,用于控制标签隐藏。',
      help: '用于控制标签页隐藏。',
      required: false,
      allowClear: true,
      options: modules,
      controlFields: [
        {field: 'controlField', notNull: true},
      ],
    },
    {
      type: 'text',
      field: 'controlField',
      label: '禁用字段',
      initval: setting.controlField || '',
      tooltip: '用于控制标签隐藏的字段,在标签中填入隐藏标记。',
      required: true,
    },
    {
      type: 'text',
      field: 'selectField',
      label: '选中字段',
      initval: setting.selectField || '',
      tooltip: '用于控制标签页初始化选中,在标签中填入选中标记,注:数据源于url参数。',
      required: false
    },
    {
      type: 'color',
      field: 'backgroundColor',
      label: '背景(标题栏)',
      initval: setting.backgroundColor || 'transparent',
      required: false
    },
    {
      type: 'radio',
      field: 'permission',
      label: '权限验证',
      initval: setting.permission || 'false',
      required: false,
      options: [
        {value: 'true', label: '启用'},
        {value: 'false', label: '禁用'},
      ],
      forbid: !appType
    },
    {
      type: 'multiselect',
      field: 'blacklist',
      label: '黑名单',
      initval: setting.blacklist || [],
      required: false,
      options: roleList,
      forbid: !!appType
    },
  ]
  return tabForm
}
src/menu/components/timeline/normal-timeline/index.jsx
@@ -44,7 +44,6 @@
        format: 'array',   // 组件属性 - 数据格式
        pageable: false,    // 组件属性 - 是否可分页
        switchable: false,  // 组件属性 - 数据是否可切换
        dataName: card.dataName || '',
        width: card.width || 24,
        name: card.name,
        subtype: card.subtype,
src/menu/components/tree/antd-tree/index.jsx
@@ -42,7 +42,6 @@
        type: card.type,
        tabId: card.tabId || '',
        parentId: card.parentId || '',
        dataName: card.dataName || '',
        format: 'array',    // 组件属性 - 数据格式
        pageable: false,    // 组件属性 - 是否可分页
        switchable: true,   // 组件属性 - 数据是否可切换
src/menu/menushell/index.jsx
@@ -124,7 +124,6 @@
        subtype: item.subtype,
        config: item.config,
        width: item.width || 24,
        dataName: Utils.getdataName(),
        name: name,
        floor: 1,   // 组件的层级
        isNew: true // 新添加标志,用于初始化
src/menu/picturecontroller/index.jsx
@@ -247,8 +247,7 @@
      <div style={{display: 'inline-block'}}>
        <Button className="mk-border-purple" onClick={this.trigger}><PictureOutlined /> 资源管理</Button>
        <Modal
          title="资源管理"
          wrapClassName="picture-control-model"
          wrapClassName="mk-pop-modal picture-control-model"
          visible={visible}
          width={1200}
          maskClosable={false}
src/menu/picturecontroller/index.scss
@@ -1,12 +1,4 @@
.picture-control-model {
  .ant-modal {
    top: 60px;
    .ant-modal-body {
      max-height: calc(100vh - 120px);
      min-height: 510px;
      padding: 10px 5px 24px;
    }
  }
  .ant-tabs-tabpane {
    padding-left: 3px;
    padding-right: 3px;
src/menu/stylecombcontrolbutton/index.jsx
@@ -60,7 +60,7 @@
      if (_type === 'cardcell') {
        _parent = _p
        MKEmitter.emit('changeCombineStyle', ['margin', 'padding', 'border', 'background', 'font'])
        MKEmitter.emit('switchMultiStyle', 'open')
      } else {
        let getParents = (box) => {
          box.components.forEach(item => {
@@ -86,7 +86,7 @@
          getParents(menu)
        }
        MKEmitter.emit('changeCombineStyle', ['margin', 'padding', 'border', 'background'])
        MKEmitter.emit('switchMultiStyle', 'open')
      }
      document.getElementById(card.uuid).classList.add('selected-control-element')
@@ -108,7 +108,7 @@
      }
      if (components.length === 0) {
        MKEmitter.emit('closeCombineStyle')
        MKEmitter.emit('switchMultiStyle', 'close')
        sessionStorage.setItem('style-control', 'true')
      }
@@ -134,7 +134,7 @@
        document.getElementById(item.uuid).classList.remove('selected-control-element')
      })
      MKEmitter.emit('closeCombineStyle')
      MKEmitter.emit('switchMultiStyle', 'close')
      this.setState({label: '批量调整', parent: null, components: []})
    }
src/menu/stylecombcontroller/index.jsx
@@ -3,7 +3,6 @@
import { is, fromJS } from 'immutable'
import { Collapse, Form, Col, InputNumber, Select, Radio, Drawer, Button } from 'antd'
import {
  ColumnHeightOutlined,
  FontSizeOutlined,
  BoldOutlined,
  LineHeightOutlined,
@@ -44,7 +43,6 @@
  }
  state = {
    options: [],
    style: {},
    borposition: 'outer'
  }
@@ -54,8 +52,7 @@
  }
  componentDidMount () {
    MKEmitter.addListener('changeCombineStyle', this.initStyle)
    MKEmitter.addListener('closeCombineStyle', this.closeStyle)
    MKEmitter.addListener('switchMultiStyle', this.switchMultiStyle)
  }
  /**
@@ -65,24 +62,21 @@
    this.setState = () => {
      return
    }
    MKEmitter.removeListener('changeCombineStyle', this.initStyle)
    MKEmitter.removeListener('closeCombineStyle', this.closeStyle)
    MKEmitter.removeListener('switchMultiStyle', this.switchMultiStyle)
  }
  closeStyle = () => {
    this.setState({
      visible: false,
      options: []
    })
  }
  initStyle = (options) => {
  switchMultiStyle = (type) => {
    if (type === 'open') {
    this.setState({
      visible: true,
      style: {},
      options: options,
      borposition: 'outer'
    })
    } else {
      this.setState({
        visible: false
      })
    }
  }
  onCloseDrawer = () => {
@@ -246,7 +240,6 @@
  }
  render () {
    const { options, borposition } = this.state
    const formItemLayout = {
      labelCol: {
        xs: { span: 24 },
@@ -275,19 +268,8 @@
      >
        <div className="menu-combine-style-controller">
          <Form {...formItemLayout}>
            <Collapse expandIconPosition="right" destroyInactivePanel={true} defaultActiveKey={options[0]}>
              {options.includes('height') ? <Panel header="高度" key="height">
                <Col span={24}>
                  <Form.Item
                    colon={false}
                    label={<ColumnHeightOutlined title="高度" />}
                    labelCol={{xs: { span: 24 }, sm: { span: 4 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 20 }} }
                  >
                    <StyleInput defaultValue={''} options={['px', 'vh', 'vw']} onChange={this.changeHeight}/>
                  </Form.Item>
                </Col>
              </Panel> : null}
              {options.includes('font') ? <Panel header="字体" key="font">
            <Collapse expandIconPosition="right" destroyInactivePanel={true} defaultActiveKey="margin">
              <Panel header="字体" key="font">
                <Col span={12}>
                  <Form.Item colon={false} label={<FontSizeOutlined title="字体大小"/>}>
                    <InputNumber defaultValue={''} min={12} max={100} precision={0} onChange={this.changeFontSize} />
@@ -371,8 +353,8 @@
                    </Radio.Group>
                  </Form.Item>
                </Col>
              </Panel> : null}
              {options.includes('background') ? <Panel header="背景" key="background">
              </Panel>
              <Panel header="背景" key="background">
                <Col span={24}>
                  <Form.Item
                    colon={false}
@@ -382,8 +364,8 @@
                    <ColorSketch onChange={this.changeBackgroundColor} />
                  </Form.Item>
                </Col>
              </Panel> : null}
              {options.includes('border') ? <Panel header="边框" key="border">
              </Panel>
              <Panel header="边框" key="border">
                <Col span={24}>
                  <Form.Item
                    colon={false}
@@ -405,36 +387,12 @@
                    label={<BorderOuterOutlined title="边框样式"/>}
                    labelCol={{xs: { span: 24 }, sm: { span: 4 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 20 }} }
                  >
                    {borposition === 'outer' ? <Select defaultValue={'solid'} onChange={this.changeBorderStyle}>
                    <Select defaultValue={'solid'} onChange={this.changeBorderStyle}>
                      <Option value="solid">实线</Option>
                      <Option value="dotted">点划线</Option>
                      <Option value="dashed">虚线</Option>
                      <Option value="double">双线</Option>
                    </Select> : null}
                    {borposition === 'left' ? <Select defaultValue={'solid'} onChange={this.changeBorderStyle}>
                      <Option value="solid">实线</Option>
                      <Option value="dotted">点划线</Option>
                      <Option value="dashed">虚线</Option>
                      <Option value="double">双线</Option>
                    </Select> : null}
                    {borposition === 'right' ? <Select defaultValue={'solid'} onChange={this.changeBorderStyle}>
                      <Option value="solid">实线</Option>
                      <Option value="dotted">点划线</Option>
                      <Option value="dashed">虚线</Option>
                      <Option value="double">双线</Option>
                    </Select> : null}
                    {borposition === 'top' ? <Select defaultValue={'solid'} onChange={this.changeBorderStyle}>
                      <Option value="solid">实线</Option>
                      <Option value="dotted">点划线</Option>
                      <Option value="dashed">虚线</Option>
                      <Option value="double">双线</Option>
                    </Select> : null}
                    {borposition === 'bottom' ? <Select defaultValue={'solid'} onChange={this.changeBorderStyle}>
                      <Option value="solid">实线</Option>
                      <Option value="dotted">点划线</Option>
                      <Option value="dashed">虚线</Option>
                      <Option value="double">双线</Option>
                    </Select> : null}
                    </Select>
                  </Form.Item>
                </Col>
                <Col span={24}>
@@ -443,11 +401,7 @@
                    label={<ColumnWidthOutlined title="边框宽度"/>}
                    labelCol={{xs: { span: 24 }, sm: { span: 4 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 20 }} }
                  >
                    {borposition === 'outer' ? <StyleInput defaultValue={''} options={['px']} onChange={this.changeBorderWidth}/> : null}
                    {borposition === 'left' ? <StyleInput defaultValue={''} options={['px']} onChange={this.changeBorderWidth}/> : null}
                    {borposition === 'right' ? <StyleInput defaultValue={''} options={['px']} onChange={this.changeBorderWidth}/> : null}
                    {borposition === 'top' ? <StyleInput defaultValue={''} options={['px']} onChange={this.changeBorderWidth}/> : null}
                    {borposition === 'bottom' ? <StyleInput defaultValue={''} options={['px']} onChange={this.changeBorderWidth}/> : null}
                    <StyleInput defaultValue={''} options={['px']} onChange={this.changeBorderWidth}/>
                  </Form.Item>
                </Col>
                <Col span={24}>
@@ -456,11 +410,7 @@
                    label={<BgColorsOutlined title="边框颜色"/>}
                    labelCol={{xs: { span: 24 }, sm: { span: 4 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 20 }} }
                  >
                    {borposition === 'outer' ? <ColorSketch onChange={this.changeBorderColor} /> : null}
                    {borposition === 'left' ? <ColorSketch onChange={this.changeBorderColor} /> : null}
                    {borposition === 'right' ? <ColorSketch onChange={this.changeBorderColor} /> : null}
                    {borposition === 'top' ? <ColorSketch onChange={this.changeBorderColor} /> : null}
                    {borposition === 'bottom' ? <ColorSketch onChange={this.changeBorderColor} /> : null}
                    <ColorSketch onChange={this.changeBorderColor} />
                  </Form.Item>
                </Col>
                <Col span={24}>
@@ -472,8 +422,8 @@
                    <StyleInput defaultValue={'0px'} options={['px', '%']} onChange={(val) => this.changeNormalStyle(val, 'borderRadius')}/>
                  </Form.Item>
                </Col>
              </Panel> : null}
              {options.includes('shadow') ? <Panel header="阴影" key="shadow">
              </Panel>
              <Panel header="阴影" key="shadow">
                <Col span={24}>
                  <Form.Item
                    colon={false}
@@ -483,8 +433,8 @@
                    <ColorSketch onChange={this.changeShadowColor} />
                  </Form.Item>
                </Col>
              </Panel> : null}
              {options.includes('margin') ? <Panel header="外边距" key="margin">
              </Panel>
              <Panel header="外边距" key="margin">
                <Col span={24}>
                  <Form.Item
                    colon={false}
@@ -521,8 +471,8 @@
                    <StyleInput defaultValue={''} options={['px', 'vh', 'vw']} onChange={(val) => this.changeNormalStyle(val, 'marginRight')}/>
                  </Form.Item>
                </Col>
              </Panel> : null}
              {options.includes('padding') ? <Panel header="内边距" key="padding">
              </Panel>
              <Panel header="内边距" key="padding">
                <Col span={24}>
                  <Form.Item
                    colon={false}
@@ -559,7 +509,7 @@
                    <StyleInput defaultValue={''} options={['px', 'vh', 'vw']} onChange={(val) => this.changeNormalStyle(val, 'paddingRight')}/>
                  </Form.Item>
                </Col>
              </Panel> : null}
              </Panel>
            </Collapse>
          </Form>
          <div style={{textAlign: 'right'}}>
src/menu/tableshell/card.jsx
@@ -1,5 +1,5 @@
import React from 'react'
import { useDrag, useDrop } from 'react-dnd'
import { useDrop } from 'react-dnd'
import asyncComponent from '@/utils/asyncComponent'
import './index.scss'
@@ -7,48 +7,24 @@
const AntvTabs = asyncComponent(() => import('@/menu/components/tabs/antv-tabs'))
const BaseTable = asyncComponent(() => import('@/menu/components/table/base-table'))
const Card = ({ id, card, moveCard, findCard, delCard, updateConfig }) => {
  const originalIndex = findCard(id).index
  const [{ isDragging }, drag] = useDrag({
    item: { type: 'menu', id, originalIndex },
    collect: monitor => ({
      isDragging: monitor.isDragging(),
    }),
  })
const Card = ({ id, card, delCard, updateConfig }) => {
  const [, drop] = useDrop({
    accept: 'menu',
    canDrop: () => true,
    drop: (item) => {
      const { id: draggedId, originalIndex } = item
      if (originalIndex === undefined) {
        item.dropTargetId = id
      } else if (draggedId) {
        if (draggedId === id) return
        const { index: originIndex } = findCard(draggedId)
        if (originIndex === -1) return
        const { index: overIndex } = findCard(id)
        moveCard(draggedId, overIndex)
      }
    }
  })
  let style = { opacity: 1}
  if (isDragging) {
    style = { opacity: 0.3}
  }
  const getCardComponent = () => {
    if (card.type === 'table') {
      return (<BaseTable card={card} updateConfig={updateConfig} deletecomponent={delCard}/>)
      return (<BaseTable card={card} updateConfig={updateConfig}/>)
    } else if (card.type === 'tabs') {
      return (<AntvTabs tabs={card} updateConfig={updateConfig} deletecomponent={delCard}/>)
    }
  }
  return (
    <div className={'ant-col mk-component-card ant-col-' + (card.width || 24)} ref={node => drag(drop(node))} style={style}>
    <div className={'ant-col mk-component-card ant-col-' + (card.width || 24)} ref={node => drop(node)}>
      {getCardComponent()}
    </div>
  )
src/menu/tableshell/index.jsx
@@ -11,12 +11,6 @@
const Container = ({menu, handleList }) => {
  const [cards, setCards] = useState(menu.components)
  const moveCard = (id, atIndex) => {
    const { card, index } = findCard(id)
    const _cards = update(cards, { $splice: [[index, 1], [atIndex, 0, card]] })
    handleList({...menu, components: _cards})
    setCards(_cards)
  }
  if (menu.components.length > cards.length) {
    setCards(menu.components)
@@ -68,29 +62,12 @@
        return
      }
      let name = ''
      let names = {
        tabs: '标签组'
      }
      let i = 1
      while (!name && names[item.component]) {
        let _name = names[item.component] + i
        if (menu.components.filter(com => com.name === _name).length === 0) {
          name = _name
        }
        i++
      }
      let newcard = {
        uuid: Utils.getuuid(),
        type: item.component,
        subtype: item.subtype,
        config: item.config,
        width: item.width || 24,
        dataName: Utils.getdataName(),
        name: name,
        floor: 1,   // 组件的层级
        isNew: true // 新添加标志,用于初始化
      }
      
@@ -119,7 +96,6 @@
            id={card.uuid}
            key={card.uuid}
            card={card}
            moveCard={moveCard}
            delCard={deleteCard}
            findCard={findCard}
            updateConfig={updateConfig}
src/menu/urlfieldcomponent/index.scss
@@ -2,6 +2,7 @@
  margin-bottom: 15px;
  .field-plus {
    line-height: 35px;
    padding-left: 16px;
    >.anticon-plus {
      color: #26C281;
      padding: 2px 5px;
src/mob/components/menubar/common-menubar/index.jsx
@@ -41,7 +41,6 @@
        format: 'object',   // 组件属性 - 数据格式
        pageable: false,    // 组件属性 - 是否可分页
        switchable: false,  // 组件属性 - 数据是否可切换
        dataName: card.dataName || '',
        width: card.width || 24,
        name: card.name,
        subtype: card.subtype,
src/mob/components/menubar/normal-menubar/index.jsx
@@ -46,7 +46,6 @@
        format: 'object',   // 组件属性 - 数据格式
        pageable: false,    // 组件属性 - 是否可分页
        switchable: false,  // 组件属性 - 数据是否可切换
        dataName: card.dataName || '',
        width: card.width || 24,
        name: card.name,
        subtype: card.subtype,
src/mob/components/navbar/normal-navbar/index.jsx
@@ -35,7 +35,6 @@
        format: 'object',   // 组件属性 - 数据格式
        pageable: false,    // 组件属性 - 是否可分页
        switchable: false,  // 组件属性 - 数据是否可切换
        dataName: card.dataName || '',
        name: card.name,
        subtype: card.subtype,
        setting: { interType: 'system' },
src/mob/components/tabs/antv-tabs/index.scss
@@ -18,6 +18,7 @@
  }
  .ant-tabs-bar.ant-tabs-top-bar {
    min-height: 32px;
    margin-bottom: 0;
  }
  .ant-tabs.ant-tabs-left, .ant-tabs.ant-tabs-bottom {
src/mob/components/tabs/tabcomponents/index.jsx
@@ -137,7 +137,6 @@
        subtype: item.subtype,
        config: item.config,
        width: item.width || 24,
        dataName: Utils.getdataName(),
        name: name,
        isNew: true                                   // 新添加标志,用于初始化
      }
src/mob/mobshell/index.jsx
@@ -168,7 +168,6 @@
        subtype: item.subtype,
        config: item.config,
        width: item.width || 24,
        dataName: Utils.getdataName(),
        name: name,
        floor: 1,   // 组件的层级
        isNew: true // 新添加标志,用于初始化
src/pc/components/login/normal-login/index.jsx
@@ -38,7 +38,6 @@
        type: card.type,
        tabId: card.tabId || '',
        parentId: card.parentId || '',
        dataName: card.dataName || '',
        width: card.width || 24,
        name: card.name,
        subtype: card.subtype,
src/pc/components/navbar/normal-navbar/index.jsx
@@ -34,7 +34,6 @@
      let _card = {
        uuid: card.uuid,
        type: card.type,
        dataName: card.dataName || '',
        name: card.name,
        subtype: card.subtype,
        wrap: { name: card.name, width: card.width || 1200, height: 50 },
src/pc/menushell/index.jsx
@@ -139,7 +139,6 @@
        subtype: item.subtype,
        config: item.config,
        width: item.width || 24,
        dataName: Utils.getdataName(),
        name: name,
        floor: 1,   // 组件的层级
        isNew: true // 新添加标志,用于初始化
src/tabviews/custom/components/group/normal-group/index.jsx
@@ -58,7 +58,7 @@
      if (!item.setting || item.setting.interType !== 'system') return
      if (!item.format) return
      if (item.dataName && (!item.pageable || (item.pageable && !item.setting.laypage)) && item.setting.onload === 'true' && item.setting.sync === 'true') {
      if ((!item.pageable || (item.pageable && !item.setting.laypage)) && item.setting.onload === 'true' && item.setting.sync === 'true') {
        let searchlist = []
        if (item.search && item.search.length > 0) {
          searchlist = Utils.initMainSearch(item.search)
src/tabviews/custom/components/share/tabtransfer/index.jsx
@@ -74,7 +74,7 @@
      if (!item.setting || item.setting.interType !== 'system') return
      if (!item.format) return
      if (item.dataName && (!item.pageable || (item.pageable && !item.setting.laypage)) && item.setting.onload === 'true' && item.setting.sync === 'true') {
      if ((!item.pageable || (item.pageable && !item.setting.laypage)) && item.setting.onload === 'true' && item.setting.sync === 'true') {
        let searchlist = []
        if (item.search && item.search.length > 0) {
          searchlist = Utils.initMainSearch(item.search)
src/tabviews/custom/index.jsx
@@ -900,10 +900,14 @@
      component.setting.customScript = _customScript // 整理后自定义脚本
      // floor    组件的层级
      // dataName 系统生成的数据源名称
      if (component.setting.sync === 'true') {
        component.dataName = Utils.getdataName()
      }
      // floor    组件的层级
      // pageable 是否分页,组件属性,不分页的组件才可以统一查询
      if (params && component.dataName && (!component.pageable || (component.pageable && !component.setting.laypage)) && component.setting.onload === 'true' && component.setting.sync === 'true') {
      if (params && (!component.pageable || (component.pageable && !component.setting.laypage)) && component.setting.onload === 'true' && component.setting.sync === 'true') {
        let searchlist = []
        if (component.search && component.search.length > 0) {
          searchlist = Utils.initMainSearch(component.search)
src/templates/calendarconfig/source.jsx
@@ -57,7 +57,7 @@
        resourceType: '0',
        options: [],
        orderType: 'asc',
        match: 'equal',
        match: '=',
      }, {
        origin: true,
        uuid: Utils.getuuid(),
src/templates/comtableconfig/source.jsx
@@ -1,8 +1,4 @@
import Utils from '@/utils/utils.js'
import zhCN from '@/locales/zh-CN/model.js'
import enUS from '@/locales/en-US/model.js'
const CommonDict = sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS
class CommonTableBaseData {
  baseConfig = {
@@ -49,7 +45,7 @@
        resourceType: '0',
        options: [],
        orderType: 'asc',
        match: 'equal',
        match: '=',
      }, {
        origin: true,
        uuid: Utils.getuuid(),
@@ -153,7 +149,7 @@
      Align: 'center',
      IsSort: 'false',
      uuid: Utils.getuuid(),
      label: CommonDict['model.operation'],
      label: '操作',
      type: 'action',
      style: 'button',
      show: 'horizontal',
@@ -195,25 +191,25 @@
  searchItems = [
    {
      type: 'search',
      label: CommonDict['model.form.text'],
      label: '文本',
      subType: 'text',
      url: ''
    },
    {
      type: 'search',
      label: CommonDict['model.form.select'],
      label: '下拉选择',
      subType: 'select',
      url: ''
    },
    {
      type: 'search',
      label: CommonDict['model.form.multiselect'],
      label: '下拉多选',
      subType: 'multiselect',
      url: ''
    },
    {
      type: 'search',
      label: CommonDict['model.form.link'],
      label: '联动菜单',
      subType: 'link',
      url: ''
    },
@@ -237,19 +233,19 @@
    },
    {
      type: 'search',
      label: CommonDict['model.form.datemonth'],
      label: '日期(月)',
      subType: 'datemonth',
      url: ''
    },
    {
      type: 'search',
      label: CommonDict['model.form.daterange'],
      label: '日期(区间)',
      subType: 'daterange',
      url: ''
    },
    {
      type: 'search',
      label: CommonDict['model.form.dategroup'],
      label: '日期(组合)',
      subType: 'group',
      url: ''
    }
@@ -258,55 +254,55 @@
  actionItems = [
    {
      type: 'action',
      label: CommonDict['model.form.popform'],
      label: '弹窗(表单)',
      subType: 'pop',
      url: ''
    },
    {
      type: 'action',
      label: CommonDict['model.form.prompt'],
      label: '提示框',
      subType: 'prompt',
      url: ''
    },
    {
      type: 'action',
      label: CommonDict['model.form.exec'],
      label: '直接执行',
      subType: 'exec',
      url: ''
    },
    {
      type: 'action',
      label: CommonDict['model.form.excelIn'],
      label: '导入Excel',
      subType: 'excelIn',
      url: ''
    },
    {
      type: 'action',
      label: CommonDict['model.form.excelOut'],
      label: '导出Excel',
      subType: 'excelOut',
      url: ''
    },
    {
      type: 'action',
      label: CommonDict['model.form.popview'],
      label: '弹窗(标签)',
      subType: 'popview',
      url: ''
    },
    {
      type: 'action',
      label: CommonDict['model.form.tab'],
      label: '标签页',
      subType: 'tab',
      url: ''
    },
    {
      type: 'action',
      label: CommonDict['model.form.newpage'],
      label: '新页面',
      subType: 'innerpage',
      url: ''
    },
    {
      type: 'action',
      label: CommonDict['model.form.funcbutton'],
      label: '功能按钮',
      subType: 'funcbutton',
      url: ''
    }
@@ -315,37 +311,37 @@
  columnItems = [
    {
      type: 'columns',
      label: CommonDict['model.form.text'],
      label: '文本',
      subType: 'text',
      url: ''
    },
    {
      type: 'columns',
      label: CommonDict['model.form.number'],
      label: '数字',
      subType: 'number',
      url: ''
    },
    {
      type: 'columns',
      label: CommonDict['model.form.picture'],
      label: '图片',
      subType: 'picture',
      url: ''
    },
    {
      type: 'columns',
      label: CommonDict['model.form.href'],
      label: '链接',
      subType: 'link',
      url: ''
    },
    {
      type: 'columns',
      label: CommonDict['model.form.textarea'],
      label: '多行文本',
      subType: 'textarea',
      url: ''
    },
    {
      type: 'columns',
      label: CommonDict['model.form.colspan'],
      label: '合并列',
      subType: 'colspan',
      url: ''
    },
@@ -360,7 +356,7 @@
  tabItems = [
    {
      type: 'tabs',
      label: CommonDict['model.menu.tab.subtable'],
      label: '子表',
      subType: 'SubTable',
    }
  ]
src/templates/sharecomponent/actioncomponent/index.jsx
@@ -426,7 +426,7 @@
            Align: 'center',
            IsSort: 'false',
            uuid: Utils.getuuid(),
            label: this.state.dict['model.operation'],
            label: '操作',
            type: 'action',
            style: 'button',
            show: 'horizontal',
@@ -647,7 +647,7 @@
            Align: 'center',
            IsSort: 'false',
            uuid: Utils.getuuid(),
            label: this.state.dict['model.operation'],
            label: '操作',
            type: 'action',
            style: 'button',
            show: 'horizontal',
src/templates/sharecomponent/tablecomponent/index.jsx
@@ -290,6 +290,7 @@
          value="请选择表名"
          onSelect={this.onTableChange}
          dropdownClassName="mk-tables"
          dropdownMatchSelectWidth={false}
          showArrow={false}
          getPopupContainer={() => containerId ? document.getElementById(containerId) : document.body}
          filterOption={(input, option) => {
src/templates/sharecomponent/tablecomponent/index.scss
@@ -31,3 +31,6 @@
    width: 33.33333333%;
  }
}
.mk-tables {
  max-width: 300px;
}
src/templates/subtableconfig/source.jsx
@@ -48,7 +48,7 @@
        resourceType: '0',
        options: [],
        orderType: 'asc',
        match: 'equal',
        match: '=',
      }, {
        origin: true,
        uuid: Utils.getuuid(),
@@ -152,7 +152,7 @@
      Align: 'center',
      IsSort: 'false',
      uuid: Utils.getuuid(),
      label: CommonDict['model.operation'],
      label: '操作',
      type: 'action',
      style: 'button',
      show: 'horizontal',
src/templates/zshare/formconfig.jsx
@@ -624,22 +624,7 @@
      label: Formdict['header.form.match'],
      initVal: card.match || 'like',
      required: true,
      options: [{
        value: 'like',
        text: 'like'
      }, {
        value: 'equal',
        text: 'equal'
      }, {
        value: 'greater',
        text: '>'
      }, {
        value: 'less',
        text: '<'
      }, {
        value: 'greaterequal',
        text: '>='
      }]
      options: []
    },
    {
      type: 'radio',
src/utils/utils-custom.js
@@ -700,17 +700,15 @@
  }
  /**
   * @description 数据源名称,用于统一查询
   * @return {String}  name
   * @description 组件名加后缀
   */
  static getdataName () {
  static getSignName () {
    let name = []
    let _options = 'abcdefghigklmnopqrstuvwxyz'
    for (let i = 0; i < 6; i++) {
    for (let i = 0; i < 3; i++) {
      name.push(_options.substr(Math.floor(Math.random() * 26), 1))
    }
    name.splice(3, 0, new Date().getTime())
    return name.join('')
    return (Math.floor(Math.random()*10) + name.join('')).toUpperCase()
  }
  /**
@@ -728,12 +726,8 @@
    item.uuid = _uuid
    if (item.dataName) {
      item.dataName = this.getdataName()
    }
    // 重置组件名称
    let sign = this.getdataName().toUpperCase().substr(-4)
    let sign = this.getSignName()
    if (item.plot) { // 图表
      item.plot.name = item.plot.name + sign
      item.name = item.plot.name
src/views/billprint/index.jsx
@@ -327,9 +327,9 @@
          component.setting.customScript = _customScript // 整理后自定义脚本
    
          // floor    组件的层级
          // dataName 系统生成的数据源名称
          // pageable 是否分页,组件属性,不分页的组件才可以统一查询
          if (component.dataName && component.setting.sync === 'true') {
          if (component.setting.sync === 'true') {
            component.dataName = Utils.getdataName()
            let param = this.getDefaultParam(component)
            _pars.push(param)
          } else {
src/views/mobdesign/index.jsx
@@ -665,7 +665,7 @@
        headerStyle: {}, parentId: '', width: 24, scripts: [], pageable: false,
        wrap: {name: 'logo', width: 24, datatype: 'static', cardType: '', blacklist: []},
        name: 'logo', floor: 1, switchable: true,
        setting:{interType: 'system'}, tabId: '', style:{paddingTop: '8vh', paddingBottom: '10vh'}, dataName: Utils.getuuid(), format: 'object', subtype: 'propcard', type: 'card', uuid: Utils.getuuid(), columns: []
        setting:{interType: 'system'}, tabId: '', style:{paddingTop: '8vh', paddingBottom: '10vh'}, format: 'object', subtype: 'propcard', type: 'card', uuid: Utils.getuuid(), columns: []
      })
      config.components.push({
@@ -674,7 +674,6 @@
        floor: 1,
        tabId: '',
        parentId: '',
        dataName: '',
        width: 24,
        name: '用户绑定',
        subtype: 'bindlogin',
@@ -697,7 +696,7 @@
        headerStyle: {}, parentId: '', width: 24, scripts: [], pageable: false,
        wrap: {name: 'Power', width: 24, datatype: 'static', cardType: '', blacklist: []},
        name: 'Power', floor: 1, switchable: true,
        setting:{interType: 'system'}, tabId: '', style:{}, dataName: Utils.getuuid(), format: 'object', subtype: 'propcard', type: 'card', uuid: Utils.getuuid(), columns: []
        setting:{interType: 'system'}, tabId: '', style:{}, format: 'object', subtype: 'propcard', type: 'card', uuid: Utils.getuuid(), columns: []
      })
    }
    
src/views/tabledesign/index.jsx
@@ -11,7 +11,9 @@
import Utils, { setGLOBFuncs } from '@/utils/utils.js'
import antdZhCN from 'antd/es/locale/zh_CN'
import MKEmitter from '@/utils/events.js'
import SourceElement from '@/templates/zshare/dragsource'
import asyncComponent from '@/utils/asyncComponent'
import Source from './source'
import '@/assets/css/design.scss'
import './index.scss'
@@ -22,15 +24,14 @@
const _locale = antdZhCN
const MenuForm = asyncComponent(() => import('./menuform'))
const TableSource = asyncComponent(() => import('./tablesource'))
const Header = asyncComponent(() => import('@/menu/header'))
const MenuShell = asyncComponent(() => import('@/menu/tableshell'))
const BgController = asyncComponent(() => import('@/pc/bgcontroller'))
const StyleController = asyncComponent(() => import('@/menu/stylecontroller'))
const ReplaceField = asyncComponent(() => import('@/menu/replaceField'))
const Versions = asyncComponent(() => import('@/menu/versions'))
const SysInterface = asyncComponent(() => import('@/menu/sysinterface'))
const UrlFieldComponent = asyncComponent(() => import('@/menu/urlfieldcomponent'))
const PictureController = asyncComponent(() => import('@/menu/picturecontroller'))
const ModalController = asyncComponent(() => import('@/menu/modalconfig/controller'))
const TableComponent = asyncComponent(() => import('@/templates/sharecomponent/tablecomponent'))
@@ -90,7 +91,6 @@
    MKEmitter.addListener('modalStatus', this.modalStatus)
    MKEmitter.addListener('changePopview', this.initPopview)
    MKEmitter.addListener('triggerMenuSave', this.triggerMenuSave)
    MKEmitter.addListener('submitComponentStyle', this.updateComponentStyle)
    MKEmitter.addListener('updateCustomComponent', this.updateCustomComponent)
    setTimeout(() => {
      if (sessionStorage.getItem('app_custom_components')) {
@@ -158,7 +158,6 @@
    MKEmitter.removeListener('modalStatus', this.modalStatus)
    MKEmitter.removeListener('changePopview', this.initPopview)
    MKEmitter.removeListener('triggerMenuSave', this.triggerMenuSave)
    MKEmitter.removeListener('submitComponentStyle', this.updateComponentStyle)
    MKEmitter.removeListener('updateCustomComponent', this.updateCustomComponent)
  }
@@ -299,28 +298,6 @@
      })
    })
    this.setState({customComponents: coms})
  }
  updateComponentStyle = (parentId, keys, style) => {
    const { config } = this.state
    if (config.uuid !== parentId) return
    let components = config.components.map(item => {
      if (keys.includes(item.uuid)) {
        item.style = {...item.style, ...style}
      }
      return item
    })
    this.setState({
      config: {...config, components},
      comloading: true
    }, () => {
      this.setState({
        comloading: false
      })
    })
  }
  initPopview = (card, btn) => {
@@ -783,6 +760,18 @@
                    {config ? <TableComponent config={config} updatetable={this.updateConfig}/> : null}
                    {config ? <Paragraph style={{padding: '15px 0px 0px 18px'}} copyable={{ text: MenuId }}>菜单ID</Paragraph> : null}
                  </Panel>
                  <Panel header="搜索" key="search">
                    {Source.searchItems.map((item, index) => (<SourceElement key={index} content={item}/>))}
                  </Panel>
                  <Panel header="按钮" key="action">
                    {Source.actionItems.map((item, index) => (<SourceElement key={index} content={item}/>))}
                  </Panel>
                  <Panel header="显示列" key="cols">
                    {Source.columnItems.map((item, index) => (<SourceElement key={index} content={item}/>))}
                  </Panel>
                  <Panel header="组件" key="component">
                    {Source.menuItems.map((item, index) => (<TableSource key={index} item={item}/>))}
                  </Panel>
                  <Panel header="页面样式" key="background">
                    {config ? <BgController config={config} updateConfig={this.updateConfig} /> : null}
                  </Panel>
@@ -795,8 +784,6 @@
                  <div>
                    <Versions MenuId={MenuId} open_edition={config ? config.open_edition : ''}/>
                    <ReplaceField type="custom" config={config} updateConfig={this.resetConfig}/>
                    <SysInterface config={config} updateConfig={this.updateConfig}/>
                    <PictureController/>
                    <Switch className="big" checkedChildren="启" unCheckedChildren="停" checked={config && config.enabled} onChange={this.onEnabledChange} />
                    <Button type="primary" id="save-config" onClick={this.submitConfig} loading={menuloading}>保存</Button>
                    <Button type="default" onClick={this.closeView}>关闭</Button>
src/views/tabledesign/source.jsx
New file
@@ -0,0 +1,177 @@
import NormalTable from '@/assets/mobimg/normal-table.png'
export default {
  searchItems: [
    {
      type: 'search',
      label: '文本',
      subType: 'text',
      url: ''
    },
    {
      type: 'search',
      label: '下拉选择',
      subType: 'select',
      url: ''
    },
    {
      type: 'search',
      label: '下拉多选',
      subType: 'multiselect',
      url: ''
    },
    {
      type: 'search',
      label: '联动菜单',
      subType: 'link',
      url: ''
    },
    {
      type: 'search',
      label: '选项卡',
      subType: 'checkcard',
      url: ''
    },
    {
      type: 'search',
      label: '日期(天)',
      subType: 'date',
      url: ''
    },
    {
      type: 'search',
      label: '日期(周)',
      subType: 'dateweek',
      url: ''
    },
    {
      type: 'search',
      label: '日期(月)',
      subType: 'datemonth',
      url: ''
    },
    {
      type: 'search',
      label: '日期(区间)',
      subType: 'daterange',
      url: ''
    },
    {
      type: 'search',
      label: '日期(组合)',
      subType: 'group',
      url: ''
    }
  ],
  actionItems: [
    {
      type: 'action',
      label: '弹窗(表单)',
      subType: 'pop',
      url: ''
    },
    {
      type: 'action',
      label: '提示框',
      subType: 'prompt',
      url: ''
    },
    {
      type: 'action',
      label: '直接执行',
      subType: 'exec',
      url: ''
    },
    {
      type: 'action',
      label: '导入Excel',
      subType: 'excelIn',
      url: ''
    },
    {
      type: 'action',
      label: '导出Excel',
      subType: 'excelOut',
      url: ''
    },
    {
      type: 'action',
      label: '弹窗(标签)',
      subType: 'popview',
      url: ''
    },
    {
      type: 'action',
      label: '标签页',
      subType: 'tab',
      url: ''
    },
    {
      type: 'action',
      label: '新页面',
      subType: 'innerpage',
      url: ''
    },
    {
      type: 'action',
      label: '功能按钮',
      subType: 'funcbutton',
      url: ''
    }
  ],
  columnItems: [
    {
      type: 'columns',
      label: '文本',
      subType: 'text',
      url: ''
    },
    {
      type: 'columns',
      label: '数字',
      subType: 'number',
      url: ''
    },
    {
      type: 'columns',
      label: '图片',
      subType: 'picture',
      url: ''
    },
    {
      type: 'columns',
      label: '链接',
      subType: 'link',
      url: ''
    },
    {
      type: 'columns',
      label: '多行文本',
      subType: 'textarea',
      url: ''
    },
    {
      type: 'columns',
      label: '合并列',
      subType: 'colspan',
      url: ''
    },
    {
      type: 'columns',
      label: '序号',
      subType: 'index',
      url: ''
    }
  ],
  tabItems: [
    {
      type: 'tabs',
      label: '子表',
      subType: 'SubTable',
    }
  ],
  menuItems: [
    { type: 'menu', url: NormalTable, component: 'table', subtype: 'basetable', title: '子表' }
  ]
}
src/views/tabledesign/tablesource/index.jsx
New file
@@ -0,0 +1,14 @@
import React from 'react'
import { useDrag } from 'react-dnd'
import './index.scss'
const TableElement = ({item}) => {
  const [, drag] = useDrag({ item })
  return (
    <div className="menu-source-item">
      <div className="property"><span>{item.title}</span></div>
      <img ref={drag} src={item.url} alt=""/>
    </div>
  )
}
export default TableElement
src/views/tabledesign/tablesource/index.scss
New file
@@ -0,0 +1,19 @@
.menu-source-item {
  display: inline-block;
  width: 100%;
  margin-bottom: 15px;
  height: auto;
  min-height: 70px;
  .property {
    font-size: 16px;
    color: rgba(0, 0, 0, 0.65);
    margin-bottom: 2px;
  }
  img {
    width: 100%;
    cursor: move;
    box-shadow: 0px 0px 1px #1890ff;
  }
}