king
2021-08-06 992f25d08ea2b5a6438ccc792a5c723b8a72f674
2021-08-06
33个文件已修改
2个文件已添加
2个文件已删除
1055 ■■■■ 已修改文件
package-lock.json 66 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
package.json 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/imgScale/index.jsx 133 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/imgScale/index.scss 238 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/normalform/index.jsx 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/card/balcony/index.jsx 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/card/balcony/index.scss 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/card/balcony/options.jsx 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/card/cardcellcomponent/dragaction/card.jsx 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/card/cardcellcomponent/elementform/index.jsx 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/card/cardcellcomponent/formconfig.jsx 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/card/cardcellcomponent/index.jsx 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/card/cardcomponent/index.jsx 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/card/cardcomponent/options.jsx 17 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/card/cardsimplecomponent/index.jsx 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/card/cardsimplecomponent/options.jsx 17 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/group/groupcomponents/card.jsx 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/group/groupcomponents/index.jsx 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/tabs/tabcomponents/card.jsx 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/tabs/tabcomponents/index.jsx 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/mob/components/tabs/tabcomponents/card.jsx 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/mob/components/tabs/tabcomponents/index.jsx 11 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/card/balcony/index.jsx 57 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/card/balcony/index.scss 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/card/cardcellList/index.jsx 77 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/card/cardcellList/index.scss 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/card/data-card/index.jsx 54 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/group/normal-group/index.jsx 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/share/normalTable/index.jsx 46 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/share/tabtransfer/index.jsx 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/table/normal-table/index.jsx 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/index.jsx 71 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/actionList/normalbutton/index.jsx 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/imgScale/index.jsx 65 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/imgScale/index.scss 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/normalTable/index.jsx 47 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/main/index.jsx 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
package-lock.json
@@ -27,9 +27,54 @@
      "integrity": "sha512-LrX0OGZtW+W6iLnTAqnTaoIsRelYeuLZWsrmBJFUXDALQphPsN8cE5DCsmoSlL0QYb94BQxINiuS70Ar/8BNgA=="
    },
    "@ant-design/icons": {
      "version": "2.1.1",
      "resolved": "https://registry.npmjs.org/@ant-design/icons/-/icons-2.1.1.tgz",
      "integrity": "sha512-jCH+k2Vjlno4YWl6g535nHR09PwCEmTBKAG6VqF+rhkrSPRLfgpU2maagwbZPLjaHuU5Jd1DFQ2KJpQuI6uG8w=="
      "version": "4.6.2",
      "resolved": "https://registry.npmjs.org/@ant-design/icons/-/icons-4.6.2.tgz",
      "integrity": "sha512-QsBG2BxBYU/rxr2eb8b2cZ4rPKAPBpzAR+0v6rrZLp/lnyvflLH3tw1vregK+M7aJauGWjIGNdFmUfpAOtw25A==",
      "requires": {
        "@ant-design/colors": "^6.0.0",
        "@ant-design/icons-svg": "^4.0.0",
        "@babel/runtime": "^7.11.2",
        "classnames": "^2.2.6",
        "rc-util": "^5.9.4"
      },
      "dependencies": {
        "@ant-design/colors": {
          "version": "6.0.0",
          "resolved": "https://registry.npmjs.org/@ant-design/colors/-/colors-6.0.0.tgz",
          "integrity": "sha512-qAZRvPzfdWHtfameEGP2Qvuf838NhergR35o+EuVyB5XvSA98xod5r4utvi4TJ3ywmevm290g9nsCG5MryrdWQ==",
          "requires": {
            "@ctrl/tinycolor": "^3.4.0"
          }
        },
        "@babel/runtime": {
          "version": "7.14.8",
          "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.14.8.tgz",
          "integrity": "sha512-twj3L8Og5SaCRCErB4x4ajbvBIVV77CGeFglHpeg5WC5FF8TZzBWXtTJ4MqaD9QszLYTtr+IsaAL2rEUevb+eg==",
          "requires": {
            "regenerator-runtime": "^0.13.4"
          }
        },
        "rc-util": {
          "version": "5.13.2",
          "resolved": "https://registry.npmjs.org/rc-util/-/rc-util-5.13.2.tgz",
          "integrity": "sha512-eYc71XXGlp96RMzg01Mhq/T3BL6OOVTDSS0urFEuvpi+e7slhJRhaHGCKy2hqJm18m9ff7VoRoptplKu60dYog==",
          "requires": {
            "@babel/runtime": "^7.12.5",
            "react-is": "^16.12.0",
            "shallowequal": "^1.1.0"
          }
        },
        "react-is": {
          "version": "16.13.1",
          "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
          "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
        },
        "regenerator-runtime": {
          "version": "0.13.9",
          "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz",
          "integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA=="
        }
      }
    },
    "@ant-design/icons-react": {
      "version": "2.0.1",
@@ -39,6 +84,11 @@
        "@ant-design/colors": "^3.1.0",
        "babel-runtime": "^6.26.0"
      }
    },
    "@ant-design/icons-svg": {
      "version": "4.1.0",
      "resolved": "https://registry.npmjs.org/@ant-design/icons-svg/-/icons-svg-4.1.0.tgz",
      "integrity": "sha512-Fi03PfuUqRs76aI3UWYpP864lkrfPo0hluwGqh7NJdLhvH4iRDc3jbJqZIvRDLHKbXrvAfPPV3+zjUccfFvWOQ=="
    },
    "@antv/adjust": {
      "version": "0.2.3",
@@ -1540,6 +1590,11 @@
      "version": "9.0.1",
      "resolved": "https://registry.npmjs.org/@csstools/normalize.css/-/normalize.css-9.0.1.tgz",
      "integrity": "sha512-6It2EVfGskxZCQhuykrfnALg7oVeiI6KclWSmGDqB0AiInVrTGB9Jp9i4/Ad21u9Jde/voVQz6eFX/eSg/UsPA=="
    },
    "@ctrl/tinycolor": {
      "version": "3.4.0",
      "resolved": "https://registry.npmjs.org/@ctrl/tinycolor/-/tinycolor-3.4.0.tgz",
      "integrity": "sha512-JZButFdZ1+/xAfpguQHoabIXkcqRRKpMrWKBkpEZZyxfY9C1DpADFB8PEqGSTeFr135SaTRfKqGKx5xSCLI7ZQ=="
    },
    "@fast-csv/format": {
      "version": "4.3.5",
@@ -3125,6 +3180,11 @@
        "warning": "~4.0.3"
      },
      "dependencies": {
        "@ant-design/icons": {
          "version": "2.1.1",
          "resolved": "https://registry.npmjs.org/@ant-design/icons/-/icons-2.1.1.tgz",
          "integrity": "sha512-jCH+k2Vjlno4YWl6g535nHR09PwCEmTBKAG6VqF+rhkrSPRLfgpU2maagwbZPLjaHuU5Jd1DFQ2KJpQuI6uG8w=="
        },
        "rc-animate": {
          "version": "2.11.1",
          "resolved": "https://registry.npmjs.org/rc-animate/-/rc-animate-2.11.1.tgz",
package.json
@@ -3,6 +3,7 @@
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "@ant-design/icons": "^4.6.2",
    "@antv/data-set": "^0.11.4",
    "@antv/g2": "^4.1.14",
    "@antv/util": "^2.0.13",
src/components/imgScale/index.jsx
New file
@@ -0,0 +1,133 @@
import React, {Component} from 'react'
import {
  RotateLeftOutlined,
  RotateRightOutlined,
  CloseOutlined,
  ZoomOutOutlined,
  ZoomInOutlined,
  LeftOutlined,
  RightOutlined
} from '@ant-design/icons'
import MKEmitter from '@/utils/events.js'
import './index.scss'
class ImgScale extends Component {
  state = {
    className: 'close',
    url: '',
    list: [],
    scale: 1,
    rotate: 0,
    index: 0
  }
  componentDidMount () {
    MKEmitter.addListener('mkImageScale', this.mkImageScale)
  }
  componentWillUnmount () {
    this.setState = () => {
      return
    }
    MKEmitter.removeListener('mkImageScale', this.mkImageScale)
  }
  mkImageScale = (src, list = []) => {
    const { url } = this.state
    if (url || !src) return
    let index = 0
    if (list.length > 0) {
      index = list.indexOf(src)
    }
    this.setState({url: src, className: 'opening', list, scale: 1, rotate: 0, index})
    setTimeout(() => {
      this.setState({className: 'open'})
    }, 300)
  }
  close = () => {
    this.setState({className: 'closeing'})
    setTimeout(() => {
      this.setState({className: 'close', url: ''})
    }, 300)
  }
  zoomIn = () => {
    this.setState({scale: this.state.scale + 1})
  }
  zoomOut = () => {
    const { scale } = this.state
    if (scale === 1) return
    this.setState({scale: scale - 1})
  }
  rotateRight = () => {
    this.setState({rotate: this.state.rotate + 90})
  }
  rotateLeft = () => {
    this.setState({rotate: this.state.rotate - 90})
  }
  prev = () => {
    const { list, index } = this.state
    this.setState({url: list[index - 1], index: index - 1})
  }
  next = () => {
    const { list, index } = this.state
    this.setState({url: list[index + 1], index: index + 1})
  }
  render() {
    const { index, url, scale, rotate, className, list } = this.state
    return (
      <div className={'mk-preview ' + className}>
        <div className="mk-image-preview-mask"></div>
        <div className="mk-image-preview-wrap">
          <div className="mk-image-preview">
            <div className="mk-image-preview-content">
              <div className="mk-image-preview-body">
                <ul className="mk-image-preview-operations">
                  <li className="mk-image-preview-operations-operation" onClick={this.close}>
                    <CloseOutlined />
                  </li>
                  <li className="mk-image-preview-operations-operation" onClick={this.zoomIn}>
                    <ZoomInOutlined />
                  </li>
                  <li className={'mk-image-preview-operations-operation ' + (scale === 1 ? 'mk-image-preview-operations-operation-disabled' : '')} onClick={this.zoomOut}>
                    <ZoomOutOutlined />
                  </li>
                  <li className="mk-image-preview-operations-operation" onClick={this.rotateRight}>
                    <RotateRightOutlined />
                  </li>
                  <li className="mk-image-preview-operations-operation" onClick={this.rotateLeft}>
                    <RotateLeftOutlined />
                  </li>
                </ul>
                <div className="mk-image-preview-img-wrapper" style={{transform: 'translate3d(0px, 0px, 0px)'}}>
                  {url ? <img className="mk-image-preview-img" alt="" src={url} style={{transform: `scale3d(${scale}, ${scale}, 1) rotate(${rotate}deg)`}}/> : null}
                </div>
                {index ? <LeftOutlined className="mk-image-preview-switch-left" onClick={this.prev}/> : null}
                {list.length > index + 1 ? <RightOutlined className="mk-image-preview-switch-right" onClick={this.next}/> : null}
              </div>
            </div>
          </div>
        </div>
      </div>
    )
  }
}
export default ImgScale
src/components/imgScale/index.scss
New file
@@ -0,0 +1,238 @@
.mk-image-preview {
  pointer-events: none;
  height: 100%;
  text-align: center;
}
.mk-image-preview.zoom-enter,
.mk-image-preview.zoom-appear {
  -webkit-transform: none;
          transform: none;
  opacity: 0;
  -webkit-animation-duration: 0.3s;
          animation-duration: 0.3s;
  -webkit-user-select: none;
     -moz-user-select: none;
      -ms-user-select: none;
          user-select: none;
}
.mk-image-preview-mask {
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  z-index: 1100;
  height: 100%;
  background-color: rgba(0, 0, 0, 0.65);
}
.mk-image-preview-mask-hidden {
  display: none;
}
.mk-image-preview-wrap {
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  overflow: auto;
  outline: 0;
  -webkit-overflow-scrolling: touch;
}
.mk-image-preview-body {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  overflow: hidden;
}
.mk-image-preview-img {
  max-width: 100%;
  max-height: 100%;
  vertical-align: middle;
  -webkit-transform: scale3d(1, 1, 1);
          transform: scale3d(1, 1, 1);
  // cursor: -webkit-grab;
  // cursor: grab;
  -webkit-transition: -webkit-transform 0.3s cubic-bezier(0.215, 0.61, 0.355, 1) 0s;
  transition: -webkit-transform 0.3s cubic-bezier(0.215, 0.61, 0.355, 1) 0s;
  transition: transform 0.3s cubic-bezier(0.215, 0.61, 0.355, 1) 0s;
  transition: transform 0.3s cubic-bezier(0.215, 0.61, 0.355, 1) 0s, -webkit-transform 0.3s cubic-bezier(0.215, 0.61, 0.355, 1) 0s;
  -webkit-user-select: none;
     -moz-user-select: none;
      -ms-user-select: none;
          user-select: none;
  pointer-events: auto;
}
.mk-image-preview-img-wrapper {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  -webkit-transition: -webkit-transform 0.3s cubic-bezier(0.215, 0.61, 0.355, 1) 0s;
  transition: -webkit-transform 0.3s cubic-bezier(0.215, 0.61, 0.355, 1) 0s;
  transition: transform 0.3s cubic-bezier(0.215, 0.61, 0.355, 1) 0s;
  transition: transform 0.3s cubic-bezier(0.215, 0.61, 0.355, 1) 0s, -webkit-transform 0.3s cubic-bezier(0.215, 0.61, 0.355, 1) 0s;
}
.mk-image-preview-img-wrapper::before {
  display: inline-block;
  width: 1px;
  height: 50%;
  margin-right: -1px;
  content: '';
}
.mk-image-preview-moving .mk-image-preview-img {
  cursor: -webkit-grabbing;
  cursor: grabbing;
}
.mk-image-preview-moving .mk-image-preview-img-wrapper {
  -webkit-transition-duration: 0s;
          transition-duration: 0s;
}
.mk-image-preview-wrap {
  z-index: 1180;
}
.mk-image-preview-operations {
  -webkit-box-sizing: border-box;
          box-sizing: border-box;
  margin: 0;
  padding: 0;
  color: rgba(0, 0, 0, 0.85);
  font-size: 14px;
  font-variant: tabular-nums;
  line-height: 1.5715;
  -webkit-font-feature-settings: 'tnum';
          font-feature-settings: 'tnum';
  position: absolute;
  top: 0;
  right: 0;
  z-index: 1;
  display: -webkit-box;
  display: -ms-flexbox;
  display: flex;
  -webkit-box-orient: horizontal;
  -webkit-box-direction: reverse;
      -ms-flex-direction: row-reverse;
          flex-direction: row-reverse;
  -webkit-box-align: center;
      -ms-flex-align: center;
          align-items: center;
  width: 100%;
  color: rgba(255, 255, 255, 0.85);
  list-style: none;
  background: rgba(0, 0, 0, 0.5);
  pointer-events: auto;
}
.mk-image-preview-operations-operation {
  margin-left: 12px;
  padding: 10px 12px;
  cursor: pointer;
  font-size: 18px;
}
.mk-image-preview-operations-operation-disabled {
  color: rgba(255, 255, 255, 0.25);
  pointer-events: none;
}
.mk-image-preview-operations-operation:last-of-type {
  margin-left: 0;
}
.mk-image-preview-switch-left,
.mk-image-preview-switch-right {
  font-size: 20px;
  position: absolute;
  top: 50%;
  right: 10px;
  z-index: 1;
  display: -webkit-box;
  display: -ms-flexbox;
  display: flex;
  -webkit-box-align: center;
      -ms-flex-align: center;
          align-items: center;
  -webkit-box-pack: center;
      -ms-flex-pack: center;
          justify-content: center;
  width: 44px;
  height: 44px;
  margin-top: -22px;
  color: rgba(255, 255, 255, 0.85);
  background: rgba(0, 0, 0, 0.1);
  border-radius: 50%;
  cursor: pointer;
  pointer-events: auto;
}
.mk-image-preview-switch-left {
  left: 10px;
}
.mk-image-preview-switch-right {
  right: 10px;
}
.mk-drawer.mk-drawer-open .mk-drawer-mask {
  height: 100%;
  opacity: 1;
  transition: none;
  -webkit-animation: antdDrawerFadeIn 0.3s cubic-bezier(0.7, 0.3, 0.1, 1);
          animation: antdDrawerFadeIn 0.3s cubic-bezier(0.7, 0.3, 0.1, 1);
  pointer-events: auto;
}
.mk-preview {
  z-index: 1100;
  opacity: 0;
}
.mk-preview.close {
  display: none;
}
.mk-preview.open {
  opacity: 1;
}
.mk-preview.opening {
  transition: none;
  -webkit-animation: antdDrawerFadeIn 0.3s cubic-bezier(0.7, 0.3, 0.1, 1);
          animation: antdDrawerFadeIn 0.3s cubic-bezier(0.7, 0.3, 0.1, 1);
  pointer-events: auto;
}
.mk-preview.closeing {
  opacity: 1;
  transition: none;
  -webkit-animation: antdDrawerFadeOut 0.3s cubic-bezier(0.7, 0.3, 0.1, 1);
          animation: antdDrawerFadeOut 0.3s cubic-bezier(0.7, 0.3, 0.1, 1);
  pointer-events: auto;
}
@-webkit-keyframes antdDrawerFadeIn {
  0% {
    opacity: 0;
  }
  100% {
    opacity: 1;
  }
}
@keyframes antdDrawerFadeIn {
  0% {
    opacity: 0;
  }
  100% {
    opacity: 1;
  }
}
@-webkit-keyframes antdDrawerFadeOut {
  0% {
    opacity: 1;
  }
  100% {
    opacity: 0;
  }
}
@keyframes antdDrawerFadeOut {
  0% {
    opacity: 1;
  }
  100% {
    opacity: 0;
  }
}
src/components/normalform/index.jsx
@@ -68,13 +68,12 @@
          visible={visible}
          width={width}
          maskClosable={false}
          okText={dict['model.submit']}
          okText={dict['model.confirm']}
          onOk={this.submit}
          onCancel={() => { this.setState({ visible: false }) }}
          destroyOnClose
        >
          <ModalForm
            dict={dict}
            formlist={formlist}
            inputSubmit={this.submit}
            wrappedComponentRef={(inst) => this.Ref = inst}
src/menu/components/card/balcony/index.jsx
@@ -1,7 +1,7 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import { is, fromJS } from 'immutable'
import { Icon, Popover } from 'antd'
import { Icon, Popover, Checkbox } from 'antd'
import asyncComponent from '@/utils/asyncComponent'
import asyncIconComponent from '@/utils/asyncIconComponent'
@@ -227,6 +227,7 @@
        } trigger="hover">
          <Icon type="tool" />
        </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>
    )
src/menu/components/card/balcony/index.scss
@@ -6,7 +6,17 @@
  background-repeat: no-repeat;
  background-size: cover;
  min-height: 30px;
  display: flex;
  
  .check-all {
    width: 70px;
    display: flex;
    justify-content: center;
    align-items: center;
  }
  .model-menu-card-cell-list {
    flex: 1;
  }
  .card-control {
    position: absolute;
    top: 0px;
src/menu/components/card/balcony/options.jsx
@@ -75,6 +75,7 @@
      field: 'supModule',
      label: '上级组件',
      initval: wrap.supModule || '',
      // tooltip: '当上级组件不存在或没有权限时,当前组件不显示。',
      required: true,
      options: supmodules
    },
@@ -95,6 +96,7 @@
      field: 'syncModule',
      label: '同步组件',
      initval: wrap.syncModule || '',
      tooltip: '当同步组件不存在或没有权限时,当前组件不显示。',
      required: true,
      options: modules
    },
src/menu/components/card/cardcellcomponent/dragaction/card.jsx
@@ -141,6 +141,12 @@
          {`${card.prefix || ''}${moment().format(card.dateFormat)}${card.postfix || ''}`}
        </div>
      )
    } else if (card.eleType === 'formula') {
      return (
        <div className="ant-mk-date">
          {`${card.prefix || ''}${card.formula}${card.postfix || ''}`}
        </div>
      )
    }
  }
@@ -158,7 +164,7 @@
        <Icon className="copy" title="复制" type="copy" onClick={() => copyCard(id)} />
        <Icon className="close" title="删除" type="close" onClick={() => delCard(id)} />
        <Icon className="style" title="调整样式" onClick={() => changeStyle(id)} type="font-colors" />
        {['text', 'number', 'slider', 'sequence'].includes(card.eleType) ? <MarkColumn columns={fields} type={card.eleType} marks={card.marks} onSubmit={(vals) => updateMarks({...card, marks: vals})} /> : null }
        {['text', 'number', 'slider', 'sequence', 'formula'].includes(card.eleType) ? <MarkColumn columns={fields} type={card.eleType} marks={card.marks} onSubmit={(vals) => updateMarks({...card, marks: vals})} /> : null }
      </div>
    } trigger="hover">
      <div ref={node => drag(drop(node))} className={'ant-col card-cell ant-col-' + card.width}>
src/menu/components/card/cardcellcomponent/elementform/index.jsx
@@ -16,7 +16,7 @@
  sequence: ['eleType', 'width'],
  text: ['eleType', 'datatype', 'format', 'width', 'height', 'prefix', 'postfix', 'link'],
  number: ['eleType', 'datatype', 'format', 'width', 'height', 'prefix', 'postfix'],
  picture: ['eleType', 'datatype', 'width', 'lenWidRadio', 'maxWidth', 'link'],
  picture: ['eleType', 'datatype', 'width', 'lenWidRadio', 'maxWidth', 'link', 'scale'],
  video: ['eleType', 'datatype', 'width', 'aspectRatio', 'autoPlay', 'loop'],
  icon: ['eleType', 'icon', 'datatype', 'width'],
  slider: ['eleType', 'datatype', 'width', 'color', 'maxValue'],
@@ -24,6 +24,7 @@
  barcode: ['eleType', 'datatype', 'width', 'barHeight', 'displayValue', 'interval'],
  qrcode: ['eleType', 'datatype', 'width', 'qrWidth', 'color', 'url'],
  currentDate: ['eleType', 'width', 'dateFormat', 'prefix', 'postfix'],
  formula: ['eleType', 'width', 'height', 'prefix', 'postfix', 'formula'],
}
class MainSearch extends Component {
@@ -299,7 +300,7 @@
                    message: formRule.input.message
                  }
                ]
              })(<TextArea rows={2} disabled={item.readonly} />)}
              })(<TextArea rows={2} disabled={item.readonly} placeholder={item.placeholder || ''} />)}
            </Form.Item>
          </Col>
        )
src/menu/components/card/cardcellcomponent/formconfig.jsx
@@ -20,6 +20,7 @@
    { value: 'barcode', text: '条形码'},
    { value: 'qrcode', text: '二维码'},
    { value: 'currentDate', text: '当前时间'},
    { value: 'formula', text: '公式'},
  ]
  if (type === 'table' || (type === 'card' && subtype === 'datacard')) {
@@ -295,6 +296,17 @@
      required: false,
    },
    {
      type: 'radio',
      key: 'scale',
      label: '图片放大',
      initVal: card.scale || 'false',
      required: false,
      options: [
        { value: 'false', text: '不可以' },
        { value: 'true', text: '可以' }
      ]
    },
    {
      type: 'select',
      key: 'aspectRatio',
      label: '长宽比',
@@ -328,7 +340,6 @@
      forbid: !isApp,
      options: [
        { value: '', text: '无' },
        // { value: 'page', text: '菜单' },
        { value: 'linkpage', text: '关联菜单' },
        { value: 'custom', text: '链接' }
      ]
@@ -385,6 +396,15 @@
      required: true,
      options: []
    },
    {
      type: 'textarea',
      key: 'formula',
      label: '公式',
      initVal: card.formula || '',
      tooltip: '执行时会使用查询到的数据替换相应的字段,展示获得的结果。',
      placeholder: '例如:@price@ * @number@',
      required: true
    },
  ]
  return forms
src/menu/components/card/cardcellcomponent/index.jsx
@@ -178,7 +178,7 @@
  resetCardStyle = (card, style) => {
    let _card = fromJS(card).toJS()
    
    if (_card.eleType === 'text' || _card.eleType === 'number') {
    if (['text', 'number', 'formula'].includes(_card.eleType)) {
      _card.style = style
      let fontSize = 14
@@ -315,6 +315,8 @@
      elements: _elements,
      visible: false,
      actvisible: false
    }, () => {
      this.props.updateElement(_elements)
    })
  }
@@ -332,7 +334,7 @@
          if (res.eleType === 'splitline' && cell.eleType !== 'splitline') {
            res.style.paddingTop = '5px'
            res.style.paddingBottom = '5px'
          } else if (res.eleType === 'text' || res.eleType === 'number') {
          } else if (['text', 'number', 'formula'].includes(res.eleType)) {
            let fontSize = 14
            let lineHeight = 1.5
            let line = res.height || null
src/menu/components/card/cardcomponent/index.jsx
@@ -178,11 +178,6 @@
  updateSetting = (res) => {
    const { card, side } = this.state
    if (res.appmenu) {
      res.menu = res.appmenu
    }
    delete res.appmenu
    this.setState({
      card: {...card, setting: res}
    })
src/menu/components/card/cardcomponent/options.jsx
@@ -101,29 +101,18 @@
      ],
      controlFields: [
        {field: 'menu', values: ['menu']},
        {field: 'appmenu', values: ['menu']},
        {field: 'linkurl', values: ['link']},
        {field: 'open', values: ['menu', 'link']},
        {field: 'joint', values: ['menu', 'link']},
      ]
    },
    {
      type: 'cascader',
      type: appType ? 'select' : 'cascader',
      field: 'menu',
      label: '菜单',
      initval: setting.menu || [],
      required: true,
      options: menulist,
      forbid: !!appType
    },
    {
      type: 'select',
      field: 'appmenu',
      label: '关联菜单',
      initval: setting.menu || '',
      initval: setting.menu || (appType ? '' : []),
      required: true,
      options: appmenulist,
      forbid: !appType
      options: appType ? appmenulist : menulist,
    },
    {
      type: 'textarea',
src/menu/components/card/cardsimplecomponent/index.jsx
@@ -146,11 +146,6 @@
  updateSetting = (res) => {
    const { card } = this.state
    if (res.appmenu) {
      res.menu = res.appmenu
    }
    delete res.appmenu
    let _card = {...card, setting: res}
    this.setState({ card: _card })
src/menu/components/card/cardsimplecomponent/options.jsx
@@ -112,29 +112,18 @@
      ],
      controlFields: [
        {field: 'menu', values: ['menu']},
        {field: 'appmenu', values: ['menu']},
        {field: 'linkurl', values: ['link']},
        {field: 'open', values: ['menu', 'link']},
        {field: 'joint', values: ['menu', 'link']},
      ]
    },
    {
      type: 'cascader',
      type: appType ? 'select' : 'cascader',
      field: 'menu',
      label: '菜单',
      initval: setting.menu || [],
      required: true,
      options: menulist,
      forbid: !!appType
    },
    {
      type: 'select',
      field: 'appmenu',
      label: '关联菜单',
      initval: setting.menu || '',
      initval: setting.menu || (appType ? '' : []),
      required: true,
      options: appmenulist,
      forbid: !appType
      options: appType ? appmenulist : menulist,
    },
    {
      type: 'textarea',
src/menu/components/group/groupcomponents/card.jsx
@@ -18,6 +18,7 @@
const AntvDashboard = asyncComponent(() => import('@/menu/components/chart/antv-dashboard'))
const CarouselDataCard = asyncComponent(() => import('@/menu/components/carousel/data-card'))
const CarouselPropCard = asyncComponent(() => import('@/menu/components/carousel/prop-card'))
const Balcony = asyncComponent(() => import('@/menu/components/card/balcony'))
const CodeSandbox = asyncComponent(() => import('@/menu/components/code/sandbox'))
const Card = ({ id, card, moveCard, findCard, delCard, updateConfig }) => {
@@ -84,6 +85,8 @@
      return (<BraftEditor card={card} updateConfig={updateConfig} deletecomponent={delCard}/>)
    } else if (card.type === 'code') {
      return (<CodeSandbox card={card} updateConfig={updateConfig} deletecomponent={delCard}/>)
    } else if (card.type === 'balcony') {
      return (<Balcony card={card} updateConfig={updateConfig} deletecomponent={delCard}/>)
    }
  }
src/menu/components/group/groupcomponents/index.jsx
@@ -67,7 +67,7 @@
      let name = ''
      let names = {
        bbar: '柱状图',
        bar: '柱状图',
        line: '折线图',
        tabs: '标签组',
        pie: '饼图',
@@ -81,6 +81,7 @@
        dashboard: '仪表盘',
        scatter: '散点图',
        tree: '树形列表',
        balcony: '浮动卡',
        card: '卡片'
      }
      let i = 1
src/menu/components/tabs/tabcomponents/card.jsx
@@ -10,6 +10,7 @@
const AntvDashboard = asyncComponent(() => import('@/menu/components/chart/antv-dashboard'))
const AntvScatter = asyncComponent(() => import('@/menu/components/chart/antv-scatter'))
const AntvTabs = asyncComponent(() => import('@/menu/components/tabs/antv-tabs'))
const Balcony = asyncComponent(() => import('@/menu/components/card/balcony'))
const DataCard = asyncComponent(() => import('@/menu/components/card/data-card'))
const PropCard = asyncComponent(() => import('@/menu/components/card/prop-card'))
const NormalTree = asyncComponent(() => import('@/menu/components/tree/antd-tree'))
@@ -93,6 +94,8 @@
      return (<BraftEditor card={card} updateConfig={updateConfig} deletecomponent={delCard}/>)
    } else if (card.type === 'code') {
      return (<CodeSandbox card={card} updateConfig={updateConfig} deletecomponent={delCard}/>)
    } else if (card.type === 'balcony') {
      return (<Balcony card={card} updateConfig={updateConfig} deletecomponent={delCard}/>)
    }
  }
src/menu/components/tabs/tabcomponents/index.jsx
@@ -92,7 +92,7 @@
      let name = ''
      let names = {
        bbar: '柱状图',
        bar: '柱状图',
        line: '折线图',
        tabs: '标签组',
        pie: '饼图',
@@ -106,6 +106,7 @@
        dashboard: '仪表盘',
        scatter: '散点图',
        tree: '树形列表',
        balcony: '浮动卡',
        card: '卡片'
      }
      let i = 1
src/mob/components/tabs/tabcomponents/card.jsx
@@ -22,6 +22,7 @@
const NormalGroup = asyncComponent(() => import('@/menu/components/group/normal-group'))
const BraftEditor = asyncComponent(() => import('@/menu/components/editor/braft-editor'))
const NormalMenuBar = asyncComponent(() => import('@/mob/components/menubar/normal-menubar'))
const Balcony = asyncComponent(() => import('@/menu/components/card/balcony'))
const CodeSandbox = asyncComponent(() => import('@/menu/components/code/sandbox'))
const Card = ({ id, card, moveCard, findCard, delCard, updateConfig }) => {
@@ -96,6 +97,8 @@
      return (<NormalMenuBar card={card} updateConfig={updateConfig} deletecomponent={delCard}/>)
    } else if (card.type === 'code') {
      return (<CodeSandbox card={card} updateConfig={updateConfig} deletecomponent={delCard}/>)
    } else if (card.type === 'balcony') {
      return (<Balcony card={card} updateConfig={updateConfig} deletecomponent={delCard}/>)
    }
  }
src/mob/components/tabs/tabcomponents/index.jsx
@@ -92,7 +92,7 @@
      let name = ''
      let names = {
        bbar: '柱状图',
        bar: '柱状图',
        line: '折线图',
        tabs: '标签组',
        pie: '饼图',
@@ -102,12 +102,13 @@
        editor: '富文本',
        code: '自定义',
        carousel: '轮播',
        form: '表单',
        dashboard: '仪表盘',
        scatter: '散点图',
        form: '表单',
        card: '卡片',
        navbar: '导航栏',
        menubar: '菜单栏',
        tree: '树形列表',
        card: '卡片'
        balcony: '浮动卡',
        login: '登录'
      }
      let i = 1
      
src/tabviews/custom/components/card/balcony/index.jsx
@@ -1,7 +1,7 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import { is, fromJS } from 'immutable'
import { Spin, notification } from 'antd'
import { Spin, notification, Checkbox } from 'antd'
import Api from '@/api'
// import Utils from '@/utils/utils.js'
@@ -15,7 +15,6 @@
class BalconyComponent extends Component {
  static propTpyes = {
    BID: PropTypes.any,
    menu: PropTypes.object,
    data: PropTypes.array,
    config: PropTypes.object,
    menuType: PropTypes.any,
@@ -28,11 +27,13 @@
    loading: false,
    sync: false,
    data: {},
    show: true
    syncData: [],
    show: true,
    checked: false
  }
  UNSAFE_componentWillMount () {
    const { data, BID, menu } = this.props
    const { data, BID } = this.props
    let _config = fromJS(this.props.config).toJS()
    let _cols = new Map()
@@ -75,32 +76,11 @@
    let show = true
    let syncConfig = null
    if (_config.wrap.linkType === 'sync') {
      _config.wrap.syncModule = _config.wrap.syncModule.pop()
      let filterComponent = (components) => {
        components.forEach(item => {
          if (syncConfig) return
          if (item.type === 'tabs') {
            item.subtabs.forEach(tab => {
              filterComponent(tab.components)
            })
          } else if (item.type === 'group') {
            filterComponent(item.components)
          } else if (_config.wrap.syncModule === item.uuid) {
            syncConfig = {
              uuid: item.uuid,
              wrap: item.wrap,
              setting: item.setting,
              columns: item.columns
            }
          }
        })
      }
      syncConfig = _config.syncConfig
      filterComponent(menu.components)
      _config.elements = _config.elements.map(item => {
        if (item.eleType === 'button') {
          item.$syncModule = _config.wrap.syncModule
        if (item.eleType === 'button' || item.eleType === 'formula') {
          item.$sync = true
        }
        return item
      })
@@ -128,6 +108,7 @@
  componentDidMount () {
    MKEmitter.addListener('reloadData', this.reloadData)
    MKEmitter.addListener('syncBalconyData', this.syncBalconyData)
    MKEmitter.addListener('resetSelectLine', this.resetParentParam)
    MKEmitter.addListener('refreshByButtonResult', this.refreshByButtonResult)
  }
@@ -141,6 +122,7 @@
      return
    }
    MKEmitter.removeListener('reloadData', this.reloadData)
    MKEmitter.removeListener('syncBalconyData', this.syncBalconyData)
    MKEmitter.removeListener('resetSelectLine', this.resetParentParam)
    MKEmitter.removeListener('refreshByButtonResult', this.refreshByButtonResult)
  }
@@ -199,6 +181,14 @@
      supModule && MKEmitter.emit('reloadData', supModule, (BID || 'empty'))
      btn.$tabId && MKEmitter.emit('refreshPopButton', btn.$tabId)
    }
  }
  syncBalconyData = (menuId, data, checked) => {
    const { syncConfig } = this.state
    if (!syncConfig || syncConfig.uuid !== menuId) return
    this.setState({syncData: data, checked})
  }
  resetParentParam = (MenuID, id) => {
@@ -281,8 +271,14 @@
    }
  }
  checkAll = (e) => {
    const { syncConfig } = this.state
    MKEmitter.emit('mkCheckAll', syncConfig.uuid, e.target.checked)
  }
  render() {
    const { config, loading, data, show, syncConfig } = this.state
    const { config, loading, data, show, syncConfig, syncData, checked } = this.state
    return (
      <div className={'custom-balcony-box' + (!show ? ' hidden' : '')} style={config.style}>
@@ -292,7 +288,8 @@
            <Spin />
          </div> : null
        }
        <CardCellComponent data={data} cards={syncConfig || config} cardCell={config} elements={config.elements}/>
        {config.wrap.checkAll === 'show' ? <div className="check-all"><Checkbox checked={checked} onChange={this.checkAll}>全选</Checkbox></div> : null}
        <CardCellComponent data={data} syncData={syncData || []} cards={syncConfig || config} cardCell={config} elements={config.elements}/>
      </div>
    )
  }
src/tabviews/custom/components/card/balcony/index.scss
@@ -4,6 +4,17 @@
  background-repeat: no-repeat;
  background-size: cover;
  position: relative;
  display: flex;
  >.check-all {
    width: 70px;
    display: flex;
    justify-content: center;
    align-items: center;
  }
  >.card-cell-list {
    flex: 1;
  }
  .card-row-list::after {
    content: ' ';
src/tabviews/custom/components/card/cardcellList/index.jsx
@@ -7,6 +7,7 @@
import asyncComponent from './asyncButtonComponent'
import asyncElementComponent from '@/utils/asyncComponent'
import MKEmitter from '@/utils/events.js'
import LostPng from '@/assets/img/lost.png'
import './index.scss'
@@ -32,6 +33,7 @@
    cards: PropTypes.object,         // 菜单配置信息
    cardCell: PropTypes.object,
    data: PropTypes.object,
    syncData: PropTypes.array,
    elements: PropTypes.array,       // 元素集
  }
@@ -473,10 +475,23 @@
        _style.cursor = 'pointer'
      }
      let scale = url && card.scale === 'true'
      return (
        <Col key={card.uuid} span={card.width}>
          <div style={_style} onClick={(e) => {this.openNewView(e, card)}}>
            <div className="ant-mk-picture" style={_imagestyle}></div>
            <div
              className={'ant-mk-picture' + (scale ? ' scale' : '')}
              onClick={(e) => {
                if (scale) {
                  e.stopPropagation()
                } else {
                  return
                }
                MKEmitter.emit('mkImageScale', url)
              }}
              style={_imagestyle}
            ></div>
          </div>
        </Col>
      )
@@ -549,8 +564,66 @@
          </div>
        </Col>
      )
    } else if (card.eleType === 'formula') {
      let val = 0
      let _style = card.style ? {...card.style} : {}
      if (card.$sync) {
        this.props.syncData.forEach(item => {
          let _val = card.formula
          Object.keys(item).forEach(key => {
            let reg = new RegExp('@' + key + '@', 'ig')
            _val = _val.replace(reg, item[key])
          })
          try {
            // eslint-disable-next-line
            _val = eval(_val)
          } catch {
            _val = 0
          }
          val += _val
        })
      } else if (data) {
        let _val = card.formula
        Object.keys(data).forEach(key => {
          let reg = new RegExp('@' + key + '@', 'ig')
          _val = _val.replace(reg, data[key])
        })
        try {
          // eslint-disable-next-line
          _val = eval(_val)
        } catch {
          _val = 0
        }
        val = _val
      }
      if (val !== '') {
        val = `${card.prefix || ''}${val}${card.postfix || ''}`
      }
      if (card.marks) {
        val = this.getMark(card.marks, _style, val)
      }
      return (
        <Col key={card.uuid} span={card.width}>
          <div style={_style}>
            <div className={'ant-mk-text line' + (card.height || '')} style={{height: card.innerHeight || 'auto'}}>{val}</div>
          </div>
        </Col>
      )
    } else if (card.eleType === 'button') {
      let _data = data.$$type === 'extendCard' ? [] : [data]
      let _data = [data]
      if (data.$$type === 'extendCard') {
        _data = []
      } else if (card.$sync) {
        _data = this.props.syncData
      }
      if (['exec', 'prompt', 'pop'].includes(card.OpenType)) {
        return (
src/tabviews/custom/components/card/cardcellList/index.scss
@@ -142,6 +142,9 @@
    background-position: center center;
    background-repeat: no-repeat;
  }
  .ant-mk-picture.scale {
    cursor: zoom-in;
  }
}
.card-cell-list::after {
  content: ' ';
src/tabviews/custom/components/card/data-card/index.jsx
@@ -2,7 +2,7 @@
import PropTypes from 'prop-types'
import { is, fromJS } from 'immutable'
import { connect } from 'react-redux'
import { Spin, Empty, notification, Row, Col, Pagination } from 'antd'
import { Spin, Empty, notification, message, Row, Col, Pagination } from 'antd'
import Api from '@/api'
import Utils from '@/utils/utils.js'
@@ -146,7 +146,7 @@
  componentDidMount () {
    MKEmitter.addListener('reloadData', this.reloadData)
    MKEmitter.addListener('getSyncData', this.getSyncData)
    MKEmitter.addListener('mkCheckAll', this.mkCheckAll)
    MKEmitter.addListener('resetSelectLine', this.resetParentParam)
    MKEmitter.addListener('queryModuleParam', this.queryModuleParam)
    MKEmitter.addListener('refreshByButtonResult', this.refreshByButtonResult)
@@ -186,18 +186,10 @@
      return
    }
    MKEmitter.removeListener('reloadData', this.reloadData)
    MKEmitter.removeListener('getSyncData', this.getSyncData)
    MKEmitter.removeListener('mkCheckAll', this.mkCheckAll)
    MKEmitter.removeListener('resetSelectLine', this.resetParentParam)
    MKEmitter.removeListener('queryModuleParam', this.queryModuleParam)
    MKEmitter.removeListener('refreshByButtonResult', this.refreshByButtonResult)
  }
  getSyncData = (syncModule, btnId) => {
    const { config, selectedData } = this.state
    if (config.uuid !== syncModule) return
    MKEmitter.emit('triggerBtnId', btnId, (selectedData || []))
  }
  /**
@@ -230,6 +222,35 @@
    } else if (position === 'popclose') {                                      // 标签关闭刷新
      config.setting.supModule && MKEmitter.emit('reloadData', config.setting.supModule, (BID || 'empty'))
      btn.$tabId && MKEmitter.emit('refreshPopButton', btn.$tabId)
    }
  }
  mkCheckAll = (menuId, checked) => {
    const { config, data } = this.state
    if (config.uuid !== menuId) return
    if (checked) {
      this.setState({
        activeKey: '',
        selectKeys: data.map((item, index) => index),
        selectedData: data
      })
      MKEmitter.emit('resetSelectLine', config.uuid, '', '')
      MKEmitter.emit('syncBalconyData', config.uuid, data, data.length > 0)
      if (data.length === 0) {
        message.warning('未获取到数据!')
      }
    } else {
      this.setState({
        activeKey: '',
        selectKeys: [],
        selectedData: []
      })
      MKEmitter.emit('resetSelectLine', config.uuid, '', '')
      MKEmitter.emit('syncBalconyData', config.uuid, [], false)
    }
  }
@@ -299,6 +320,9 @@
        loading: false
      })
      MKEmitter.emit('resetSelectLine', config.uuid, '', '')
      if (config.setting.$hasSyncModule) {
        MKEmitter.emit('syncBalconyData', config.uuid, [], false)
      }
      return
    }
@@ -346,6 +370,9 @@
        loading: false
      })
      MKEmitter.emit('resetSelectLine', config.uuid, '', '')
      if (config.setting.$hasSyncModule) {
        MKEmitter.emit('syncBalconyData', config.uuid, [], false)
      }
    } else {
      this.setState({
        loading: false
@@ -464,7 +491,7 @@
  }
  
  changeCard = (index, item) => {
    const { config, selectKeys, selectedData, activeKey } = this.state
    const { config, selectKeys, selectedData, activeKey, data } = this.state
    this.openView(item)
@@ -504,6 +531,9 @@
    })
    MKEmitter.emit('resetSelectLine', config.uuid, (_item ? _item.$$uuid : ''), _item)
    if (config.setting.$hasSyncModule) {
      MKEmitter.emit('syncBalconyData', config.uuid, _selectedData, data.length === _selectedData.length)
    }
  }
  openView = (item) => {
src/tabviews/custom/components/group/normal-group/index.jsx
@@ -28,6 +28,7 @@
const NormalTree = asyncComponent(() => import('@/tabviews/custom/components/tree/antd-tree'))
const CarouselDataCard = asyncComponent(() => import('@/tabviews/custom/components/carousel/data-card'))
const CarouselPropCard = asyncComponent(() => import('@/tabviews/custom/components/carousel/prop-card'))
const Balcony = asyncComponent(() => import('@/tabviews/custom/components/card/balcony'))
class TabTransfer extends Component {
  static propTpyes = {
@@ -221,6 +222,12 @@
            <SandBox config={item} data={data} BID={_bid} mainSearch={mainSearch} menuType={menuType} />
          </Col>
        )
      } else if (item.type === 'balcony') {
        return (
          <Col span={item.width} key={item.uuid}>
            <Balcony config={item} data={data} BID={_bid} menuType={menuType} />
          </Col>
        )
      } else {
        return null
      }
src/tabviews/custom/components/share/normalTable/index.jsx
@@ -3,7 +3,7 @@
import md5 from 'md5'
import { connect } from 'react-redux'
import { is, fromJS } from 'immutable'
import { Table, Typography, Icon, Col, Switch } from 'antd'
import { Table, Typography, Icon, Col, Switch, message } from 'antd'
import { modifyTabview } from '@/store/action'
import asyncComponent from '@/utils/asyncComponent'
@@ -496,6 +496,7 @@
  }
  componentDidMount () {
    MKEmitter.addListener('mkCheckAll', this.mkCheckAll)
    MKEmitter.addListener('resetTable', this.resetTable)
  }
@@ -506,7 +507,39 @@
    this.setState = () => {
      return
    }
    MKEmitter.removeListener('mkCheckAll', this.mkCheckAll)
    MKEmitter.removeListener('resetTable', this.resetTable)
  }
  mkCheckAll = (menuId, checked) => {
    const { MenuID, data } = this.props
    if (MenuID !== menuId) return
    if (checked) {
      this.setState({
        activeIndex: '',
        selectedRowKeys: data.map((item, index) => index)
      })
      this.props.chgSelectData(data)
      MKEmitter.emit('resetSelectLine', MenuID, '', '')
      MKEmitter.emit('syncBalconyData', MenuID, data, data.length > 0)
      if (data.length === 0) {
        message.warning('未获取到数据!')
      }
    } else {
      this.setState({
        activeIndex: '',
        selectedRowKeys: [],
      })
      this.props.chgSelectData([])
      MKEmitter.emit('resetSelectLine', MenuID, '', '')
      MKEmitter.emit('syncBalconyData', MenuID, [], false)
    }
  }
  // 字段透视
@@ -585,7 +618,7 @@
   * 
   */
  onSelectChange = selectedRowKeys => {
    const { setting } = this.props
    const { setting, MenuID, data } = this.props
    let index = ''
    let _activeIndex = null
@@ -604,13 +637,16 @@
    let selects = this.props.data.filter((item, _index) => selectedRowKeys.includes(_index))
    this.props.chgSelectData(selects)
    if (setting.$hasSyncModule) {
      MKEmitter.emit('syncBalconyData', MenuID, selects, data.length === selects.length)
    }
  }
  /**
   * @description 点击整行,触发切换, 判断是否可选,单选或多选,进行对应操作
   */
  changeRow = (record, index) => {
    const { setting } = this.props
    const { setting, MenuID, data } = this.props
    if (!setting.tableType || this.state.pickup) return
    
@@ -640,6 +676,10 @@
    let selects = this.props.data.filter((item, _index) => newkeys.includes(_index))
    
    this.props.chgSelectData(selects)
    if (setting.$hasSyncModule) {
      MKEmitter.emit('syncBalconyData', MenuID, selects, data.length === selects.length)
    }
  }
  changeTable = (pagination, filters, sorter) => {
src/tabviews/custom/components/share/tabtransfer/index.jsx
@@ -31,6 +31,7 @@
const NormalTree = asyncComponent(() => import('@/tabviews/custom/components/tree/antd-tree'))
const CarouselDataCard = asyncComponent(() => import('@/tabviews/custom/components/carousel/data-card'))
const CarouselPropCard = asyncComponent(() => import('@/tabviews/custom/components/carousel/prop-card'))
const Balcony = asyncComponent(() => import('@/tabviews/custom/components/card/balcony'))
class TabTransfer extends Component {
  static propTpyes = {
@@ -259,6 +260,12 @@
            <SandBox config={item} data={data} BID={BID} mainSearch={mainSearch} menuType={menuType} />
          </Col>
        )
      } else if (item.type === 'balcony') {
        return (
          <Col span={item.width} key={item.uuid}>
            <Balcony config={item} data={data} BID={BID} menuType={menuType} />
          </Col>
        )
      } else {
        return null
      }
src/tabviews/custom/components/table/normal-table/index.jsx
@@ -148,6 +148,9 @@
      })
      MKEmitter.emit('resetSelectLine', config.uuid, '', '') // 广播数据切换
      reset && MKEmitter.emit('resetTable', config.uuid, repage) // 列表重置
      if (setting.$hasSyncModule) {
        MKEmitter.emit('syncBalconyData', config.uuid, [], false)
      }
      return
    }
@@ -195,6 +198,9 @@
        total: result.total,
        loading: false
      })
      if (setting.$hasSyncModule) {
        MKEmitter.emit('syncBalconyData', config.uuid, [], false)
      }
    } else {
      this.setState({
        loading: false
@@ -489,14 +495,6 @@
    }
  }
  getSyncData = (syncModule, btnId) => {
    const { config, selectedData } = this.state
    if (config.uuid !== syncModule) return
    MKEmitter.emit('triggerBtnId', btnId, (selectedData || []))
  }
  UNSAFE_componentWillReceiveProps(nextProps) {
    const { sync, config, BID } = this.state
@@ -527,7 +525,6 @@
  componentDidMount () {
    MKEmitter.addListener('reloadData', this.reloadData)
    MKEmitter.addListener('getSyncData', this.getSyncData)
    MKEmitter.addListener('resetSelectLine', this.resetParentParam)
    MKEmitter.addListener('queryModuleParam', this.queryModuleParam)
    MKEmitter.addListener('refreshByButtonResult', this.refreshByButtonResult)
@@ -541,7 +538,6 @@
      return
    }
    MKEmitter.removeListener('reloadData', this.reloadData)
    MKEmitter.removeListener('getSyncData', this.getSyncData)
    MKEmitter.removeListener('resetSelectLine', this.resetParentParam)
    MKEmitter.removeListener('queryModuleParam', this.queryModuleParam)
    MKEmitter.removeListener('refreshByButtonResult', this.refreshByButtonResult)
src/tabviews/custom/index.jsx
@@ -130,7 +130,8 @@
      // 权限过滤
      let roleId = sessionStorage.getItem('role_id') || '' // 角色ID
      config.components = this.filterComponent(config.components, roleId, permAction, permMenus)
      let balMap = new Map()
      config.components = this.filterComponent(config.components, roleId, permAction, permMenus, balMap)
      
      // 获取主搜索条件
      let mainSearch = []
@@ -190,7 +191,11 @@
        })
      }
      config.components = this.formatSetting(config.components, params, mainSearch, inherit, regs)
      config.components = this.formatSetting(config.components, params, mainSearch, inherit, regs, balMap)
      if ([...balMap.keys()].length > 0) {
        config.components = this.filterBalcony(config.components, balMap)
      }
      this.setState({
        BID: BID,
@@ -439,7 +444,7 @@
    })
  }
  filterComponent = (components, roleId, permAction, permMenus) => {
  filterComponent = (components, roleId, permAction, permMenus, balMap) => {
    return components.filter(item => {
      
      if (item.style && item.style.boxShadow) {
@@ -470,7 +475,7 @@
        })
        item.subtabs = item.subtabs.map(tab => {
          tab.components = this.filterComponent(tab.components, roleId, permAction, permMenus)
          tab.components = this.filterComponent(tab.components, roleId, permAction, permMenus, balMap)
          return tab
        })
@@ -493,7 +498,7 @@
          return false
        }
        item.components = this.filterComponent(item.components, roleId, permAction, permMenus)
        item.components = this.filterComponent(item.components, roleId, permAction, permMenus, balMap)
      } else if (['pie', 'bar', 'line', 'dashboard', 'scatter'].includes(item.type)) {
        if (
          item.plot.blacklist && item.plot.blacklist.length > 0 &&
@@ -638,6 +643,10 @@
          })
        })
      } else if (item.type === 'balcony') {
        if (item.wrap.linkType === 'sync') {
          item.wrap.syncModuleId = item.wrap.syncModule.pop()
          balMap.set(item.wrap.syncModuleId, true)
        }
        item.elements = item.elements.filter(cell => {
          if (cell.eleType === 'button') {
            cell.logLabel = item.$menuname + '-' + cell.label
@@ -729,6 +738,45 @@
    })
  }
  filterBalcony = (components, balMap) => {
    return components.filter(item => {
      if (item.type === 'tabs') {
        item.subtabs = item.subtabs.map(tab => {
          tab.components = this.filterBalcony(tab.components, balMap)
          return tab
        })
      } else if (item.type === 'group') {
        item.components = this.filterBalcony(item.components, balMap)
      }
      if (item.type === 'balcony' && item.wrap.linkType === 'sync') {
        let conf = balMap.get(item.wrap.syncModuleId)
        if (!conf || conf === true) {
          return false
        }
        item.syncConfig = {
          uuid: conf.uuid,
          wrap: conf.wrap,
          setting: conf.setting,
          columns: conf.columns
        }
        if (item.wrap.checkAll === 'show') {
          if (conf.subtype === 'datacard' && conf.wrap.cardType !== 'checkbox') {
            item.wrap.checkAll = 'hidden'
          } else if (conf.subtype === 'normaltable' && conf.wrap.tableType !== 'checkbox') {
            item.wrap.checkAll = 'hidden'
          }
        }
      }
      return true
    })
  }
  getPrinter = (item, parentId) => {
    let _item = window.GLOB.UserCacheMap.get(parentId + item.uuid)
@@ -748,17 +796,17 @@
  }
  // 格式化默认设置
  formatSetting = (components, params, mainSearch, inherit, regs) => {
  formatSetting = (components, params, mainSearch, inherit, regs, balMap) => {
    return components.map(component => {
      if (component.type === 'tabs') {
        component.subtabs = component.subtabs.map(tab => {
          tab.components = this.formatSetting(tab.components, [], [], inherit, regs)
          tab.components = this.formatSetting(tab.components, [], [], inherit, regs, balMap)
          tab = {...tab, ...inherit}
          return tab
        })
        return component
      } else if (component.type === 'group') {
        component.components = this.formatSetting(component.components, [], [], inherit, regs)
        component.components = this.formatSetting(component.components, [], [], inherit, regs, balMap)
        component = {...component, ...inherit}
        return component
      }
@@ -844,6 +892,11 @@
        }
      } else if (component.floor === 1) {
        component.setting.sync = 'false'
      }
      if (balMap.has(component.uuid)) {
        component.setting.$hasSyncModule = true
        balMap.set(component.uuid, component)
      }
      return component
@@ -1012,7 +1065,7 @@
      } else if (item.type === 'balcony') {
        return (
          <Col span={item.width} key={item.uuid}>
            <Balcony menu={config} config={item} data={data} BID={_bid} menuType={menuType} />
            <Balcony config={item} data={data} BID={_bid} menuType={menuType} />
          </Col>
        )
      } else if (item.type === 'carousel' && item.subtype === 'datacard') {
src/tabviews/zshare/actionList/normalbutton/index.jsx
@@ -158,11 +158,6 @@
      return
    }
    if (btn.$syncModule && !triggerId) {
      MKEmitter.emit('getSyncData', btn.$syncModule, btn.uuid)
      return
    }
    let _this = this
    let data = record || selectedData || []
src/tabviews/zshare/imgScale/index.jsx
File was deleted
src/tabviews/zshare/imgScale/index.scss
File was deleted
src/tabviews/zshare/normalTable/index.jsx
@@ -3,7 +3,7 @@
import md5 from 'md5'
import { connect } from 'react-redux'
import { is, fromJS } from 'immutable'
import { Table, Affix, Typography, Modal, Icon } from 'antd'
import { Table, Affix, Typography, Icon } from 'antd'
import { modifyTabview } from '@/store/action'
import asyncComponent from '@/utils/asyncComponent'
@@ -17,7 +17,6 @@
const PopupButton = asyncComponent(() => import('@/tabviews/zshare/actionList/popupbutton'))
const TabButton = asyncComponent(() => import('@/tabviews/zshare/actionList/tabbutton'))
const NewPageButton = asyncComponent(() => import('@/tabviews/zshare/actionList/newpagebutton'))
const ImgScale = asyncComponent(() => import('@/tabviews/zshare/imgScale'))
class NormalTable extends Component {
  static propTpyes = {
@@ -45,8 +44,6 @@
    pageIndex: 1,         // 初始页面索引
    pageSize: 10,         // 每页数据条数
    columns: null,        // 显示列
    imgShow: false,       // 图片放大模态框
    imgData: {},          // 图片集
    lineMarks: null,      // 行标记
    activeIndex: null,    // 标记当前选中行
    rowspans: null        // 行合并字段信息
@@ -558,7 +555,9 @@
        <div className="picture-col">
          {photos && photos.map((url, i) => {
            if (item.scale === 'true') {
              return <img style={{maxHeight: maxHeight}} className="image-scale" onClick={() => this.imgScale(photos, i)} key={`${i}`} src={url} alt=""/>
              return <img style={{maxHeight: maxHeight}} className="image-scale" onClick={() => {
                MKEmitter.emit('mkImageScale', url, photos.length > 1 ? photos : '')
              }} key={`${i}`} src={url} alt=""/>
            } else {
              return <img style={{maxHeight: maxHeight}} key={`${i}`} src={url} alt=""/>
            }
@@ -871,7 +870,9 @@
          <div className="content-fence-top" style={images[0] ? {textAlign: images[0].align} : null}>
            {images.map((_img, index) => {
              if (_img.scale) {
                return <img style={{maxHeight: _img.maxHeight}} className="image-scale" onClick={() => this.imgScale(images, index)} key={`${index}`} src={_img.url} alt=""/>
                return <img style={{maxHeight: _img.maxHeight}} className="image-scale" onClick={() => {
                  MKEmitter.emit('mkImageScale', _img.url, images.length > 1 ? images.map(g => g.url) : '')
                }} key={`${index}`} src={_img.url} alt=""/>
              } else {
                return (<img style={{maxHeight: _img.maxHeight}} key={`${index}`} src={_img.url} alt=""/>)
              }
@@ -890,7 +891,9 @@
          <div className="content-fence-left" style={images[0] ? {textAlign: images[0].align} : null}>
            {images.map((_img, index) => {
              if (_img.scale) {
                return <img style={{maxHeight: _img.maxHeight}} className="image-scale" onClick={() => this.imgScale(images, index)} key={`${index}`} src={_img.url} alt=""/>
                return <img style={{maxHeight: _img.maxHeight}} className="image-scale" onClick={() => {
                  MKEmitter.emit('mkImageScale', _img.url, images.length > 1 ? images.map(g => g.url) : '')
                }} key={`${index}`} src={_img.url} alt=""/>
              } else {
                return (<img style={{maxHeight: _img.maxHeight}} key={`${index}`} src={_img.url} alt=""/>)
              }
@@ -904,24 +907,6 @@
        </div>
      )
    }
  }
  /**
   * @description 图片缩放
   */
  imgScale = (images, index) => {
    this.setState({
      imgShow: true,
      imgData: {
        list: images.map(item => {
          if (typeof(item) === 'string') {
            return item
          }
          return item.url
        }),
        index
      }
    })
  }
  /**
@@ -1232,18 +1217,6 @@
          pagination={_pagination}
        />
        {_footer ? <div className={'normal-table-footer ' + (_pagination ? 'pagination' : '')}>{_footer}</div> : null}
        <Modal
          className="image-scale-modal"
          visible={this.state.imgShow}
          width="70vw"
          maskClosable={true}
          onCancel={() => {this.setState({ imgShow: false })}}
          title={this.props.dict['main.form.picture.check']}
          footer={[<span key="close" onClick={() => {this.setState({ imgShow: false })}}>{this.props.dict['main.close']}</span>]}
          destroyOnClose
        >
          <ImgScale data={this.state.imgData}/>
        </Modal>
      </div>
    )
  }
src/views/main/index.jsx
@@ -7,6 +7,7 @@
import Header from '@/components/header'
import Sidemenu from '@/components/sidemenu'
import QueryLog from '@/components/querylog'
import ImgScale from '@/components/imgScale'
import './index.scss'
@@ -32,6 +33,7 @@
          {!isSideMenu ? <Breadview key="breadview"/> : null}
          <QueryLog />
        </ConfigProvider>
        <ImgScale />
      </div>
    )
  }