king
2021-07-13 b438c7318712385a77026885063299958f23356e
2021-07-13
15个文件已修改
4个文件已添加
931 ■■■■ 已修改文件
src/components/paste/index.jsx 72 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/paste/index.scss 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/card/balcony/index.jsx 185 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/card/balcony/wrapsetting/settingform/index.jsx 122 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/card/cardcellcomponent/index.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/share/styleInput/index.jsx 48 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/mob/mobshell/card.jsx 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/mob/modulesource/option.jsx 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pc/menushell/card.jsx 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pc/modulesource/option.jsx 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/card/balcony/index.jsx 301 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/card/balcony/index.scss 65 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/card/data-card/index.jsx 26 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/table/normal-table/index.jsx 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/index.jsx 36 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/actionList/normalbutton/index.jsx 10 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/menudesign/index.jsx 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mobdesign/index.jsx 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/pcdesign/index.jsx 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/paste/index.jsx
New file
@@ -0,0 +1,72 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import { Icon, Modal, notification } from 'antd'
import asyncComponent from '@/utils/asyncComponent'
import './index.scss'
const PasteForm = asyncComponent(() => import('@/templates/zshare/pasteform'))
class PasteController extends Component {
  static propTpyes = {
    options: PropTypes.array,
    updateConfig: PropTypes.func
  }
  state = {
    visible: false
  }
  handleMenuClick = () => {
    this.setState({visible: true})
  }
  pasteSubmit = () => {
    const { options } = this.props
    this.pasteFormRef.handleConfirm().then(res => {
      if (!options.includes(res.copyType)) {
        notification.warning({ top: 92, message: '配置信息格式错误!', duration: 5 })
        return
      }
      this.props.updateConfig(res, (result) => {
        if (result.status) {
          notification.success({
            top: 92,
            message: '粘贴成功!',
            duration: 2
          })
          this.setState({visible: false})
        } else {
          notification.success({
            top: 92,
            message: result.message,
            duration: 2
          })
        }
      })
    })
  }
  render() {
    const { visible } = this.state
    return (
      <div style={{display: 'inline-block'}}>
        <Icon type="snippets" style={{color: 'purple'}} onClick={() => {this.setState({visible: true})}} />
        <Modal
          title="粘贴"
          visible={visible}
          width={600}
          maskClosable={false}
          onOk={this.pasteSubmit}
          onCancel={() => {this.setState({visible: false})}}
          destroyOnClose
        >
          <PasteForm wrappedComponentRef={(inst) => this.pasteFormRef = inst} inputSubmit={this.pasteSubmit}/>
        </Modal>
      </div>
    )
  }
}
export default PasteController
src/components/paste/index.scss
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, Modal } from 'antd'
import { Icon, Popover } from 'antd'
import asyncComponent from '@/utils/asyncComponent'
import asyncIconComponent from '@/utils/asyncIconComponent'
@@ -16,12 +16,9 @@
const WrapComponent = asyncIconComponent(() => import('./wrapsetting'))
const CardCellComponent = asyncComponent(() => import('../cardcellcomponent'))
const CopyComponent = asyncIconComponent(() => import('@/menu/components/share/copycomponent'))
const PasteComponent = asyncIconComponent(() => import('@/menu/components/share/pastecomponent'))
const PasteComponent = asyncIconComponent(() => import('@/components/paste'))
const UserComponent = asyncIconComponent(() => import('@/menu/components/share/usercomponent'))
const ClockComponent = asyncIconComponent(() => import('@/menu/components/share/clockcomponent'))
const NormalHeader = asyncComponent(() => import('@/menu/components/share/normalheader'))
const { confirm } = Modal
class BalconyEditComponent extends Component {
  static propTpyes = {
@@ -40,7 +37,6 @@
    const { card } = this.props
    if (card.isNew) {
      // let ismob = sessionStorage.getItem('appType') === 'mob'
      let _card = {
        uuid: card.uuid,
        type: card.type,
@@ -56,7 +52,7 @@
        subtype: card.subtype,
        setting: { interType: 'system' },
        wrap: { name: card.name, width: card.width || 24, linkType: 'static', position: 'relative', datatype: 'static' },
        style: { marginLeft: '0px', marginRight: '0px', marginTop: '8px', marginBottom: '8px' },
        style: { marginLeft: '0px', marginRight: '0px', marginTop: '0px', marginBottom: '0px' },
        columns: [],
        scripts: [],
        elements: [],
@@ -87,7 +83,6 @@
  componentDidMount () {
    MKEmitter.addListener('submitStyle', this.getStyle)
    MKEmitter.addListener('submitComponentStyle', this.updateComponentStyle)
  }
  shouldComponentUpdate (nextProps, nextState) {
@@ -102,24 +97,6 @@
      return
    }
    MKEmitter.removeListener('submitStyle', this.getStyle)
    MKEmitter.removeListener('submitComponentStyle', this.updateComponentStyle)
  }
  updateComponentStyle = (parentId, keys, style) => {
    const { card } = this.state
    if (card.uuid !== parentId) return
    let subcards = card.subcards.map(item => {
      if (keys.includes(item.uuid)) {
        item.style = {...item.style, ...style}
      }
      return item
    })
    this.setState({card: {...card, subcards: []}}, () => {
      this.updateComponent({...card, subcards: subcards})
    })
  }
  /**
@@ -136,52 +113,16 @@
    this.props.updateConfig(component)
  }
  /**
   * @description 单个卡片信息更新
   */
  updateCard = (cell) => {
    let card = fromJS(this.state.card).toJS()
  updateCard = (elements) => {
    const { card } = this.state
    card.subcards = card.subcards.map(item => {
      if (item.uuid === cell.uuid) return cell
      return item
    let _card = {...card, elements: elements}
    this.setState({
      card: _card,
    })
    this.setState({card})
    this.props.updateConfig(card)
  }
  /**
   * @description 单个卡片信息更新
   */
  deleteCard = (cell) => {
    let card = fromJS(this.state.card).toJS()
    let _this = this
    confirm({
      content: '确定删除卡片吗?',
      onOk() {
        card.subcards = card.subcards.filter(item => item.uuid !== cell.uuid)
        let uuids = []
        cell.elements && cell.elements.forEach(c => {
          if (c.eleType === 'button') {
            uuids.push(c.uuid)
          }
        })
        cell.backElements && cell.backElements.forEach(c => {
          if (c.eleType === 'button') {
            uuids.push(c.uuid)
          }
        })
        MKEmitter.emit('delButtons', uuids)
        _this.setState({card})
        _this.props.updateConfig(card)
      },
      onCancel() {}
    })
    this.props.updateConfig(_card)
  }
  changeStyle = () => {
@@ -204,66 +145,63 @@
    this.props.updateConfig(_card)
  }
  addCard = () => {
    let card = fromJS(this.state.card).toJS()
  addElement = () => {
    const { card } = this.state
    let newcard = {
      uuid: Utils.getuuid(),
      setting: { width: 6, type: 'simple'},
      style: {
        borderWidth: '1px', borderColor: '#e8e8e8',
        paddingTop: '15px', paddingBottom: '15px', paddingLeft: '15px', paddingRight: '15px',
        marginLeft: '8px', marginRight: '8px', marginTop: '8px', marginBottom: '8px'
      },
      backStyle: {},
      elements: [],
      backElements: []
    }
    if (card.subcards.length > 0) {
      newcard = fromJS(card.subcards.slice(-1)[0]).toJS()
      newcard.uuid = Utils.getuuid()
      newcard.elements = newcard.elements.map(elem => {
        elem.uuid = Utils.getuuid()
        return elem
      })
      newcard.backElements = newcard.backElements.map(elem => {
        elem.uuid = Utils.getuuid()
        return elem
      })
    }
    card.subcards.push(newcard)
    let newcard = {}
    newcard.uuid = Utils.getuuid()
    newcard.focus = true
    
    this.setState({card})
    this.props.updateConfig(card)
    newcard.eleType = 'text'
    newcard.datatype = 'dynamic'
    newcard.height = 1
    // 注册事件-添加元素
    MKEmitter.emit('cardAddElement', [card.uuid, card.uuid], newcard)
  }
  move = (item, direction) => {
    let card = fromJS(this.state.card).toJS()
  addButton = () => {
    const { card } = this.state
    let dragIndex = card.subcards.findIndex(c => c.uuid === item.uuid)
    let hoverIndex = null
    let newcard = {}
    newcard.uuid = Utils.getuuid()
    newcard.focus = true
    newcard.eleType = 'button'
    newcard.label = 'button'
    newcard.sqlType = ''
    newcard.Ot = 'requiredSgl'
    newcard.OpenType = 'prompt'
    newcard.icon = ''
    newcard.class = 'primary'
    newcard.intertype = 'system'
    newcard.execSuccess = 'grid'
    newcard.execError = 'never'
    newcard.popClose = 'never'
    newcard.errorTime = 10
    newcard.verify = null
    newcard.show = 'link'
    if (direction === 'left') {
      hoverIndex = dragIndex - 1
    // 注册事件-添加元素
    MKEmitter.emit('cardAddElement', [card.uuid, card.uuid], newcard)
  }
  pasteComponent = (res, resolve) => {
    const { card } = this.state
    let type = res.copyType
    delete res.copyType
    res.uuid = Utils.getuuid()
    res.focus = true
    if (type === 'customCardElement') {
      MKEmitter.emit('cardAddElement', [card.uuid, card.uuid], res)
    } else {
      hoverIndex = dragIndex + 1
      res.eleType = 'button'
      MKEmitter.emit('cardAddElement', [card.uuid, card.uuid], res)
    }
    if (hoverIndex === -1 || hoverIndex === card.subcards.length) return
    card.subcards.splice(hoverIndex, 0, ...card.subcards.splice(dragIndex, 1))
    this.setState({card})
    this.props.updateConfig(card)
  }
  clickComponent = (e) => {
    if (sessionStorage.getItem('style-control') === 'true' || sessionStorage.getItem('style-control') === 'component') {
      e.stopPropagation()
      MKEmitter.emit('clickComponent', this.state.card)
    }
    resolve({status: true})
  }
  render() {
@@ -272,15 +210,14 @@
    let _style = resetStyle(card.style)
    return (
      <div className="menu-balcony-edit-box" style={_style} onClick={this.clickComponent} id={card.uuid}>
        <NormalHeader defaultshow="hidden" config={card} updateComponent={this.updateComponent}/>
      <div className="menu-balcony-edit-box" style={_style} id={card.uuid}>
        <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={
          <div className="mk-popover-control">
            <Icon className="plus" title="添加元素" onClick={this.addElement} type="plus" />
            <Icon className="plus" title="添加按钮" onClick={this.addButton} type="plus-square" />
            <WrapComponent config={card} updateConfig={this.updateComponent} />
            <CopyComponent type="balcony" card={card}/>
            <PasteComponent config={card} options={['cardcell']} updateConfig={this.updateComponent} />
            <PasteComponent options={['action', 'customCardElement']} updateConfig={this.pasteComponent} />
            <Icon className="style" title="调整样式" onClick={this.changeStyle} type="font-colors" />
            <ClockComponent config={card} updateConfig={this.updateComponent}/>
            <UserComponent config={card}/>
src/menu/components/card/balcony/wrapsetting/settingform/index.jsx
@@ -74,6 +74,84 @@
    }
  }
  chose = (val) => {
    let values = {}
    if (val === 'top') {
      values = {
        top: '0px',
        left: '50%',
        right: '',
        bottom: '',
        transform: 'translateX(-50%)'
      }
    } else if (val === 'top-left') {
      values = {
        top: '0px',
        left: '0px',
        right: '',
        bottom: '',
        transform: ''
      }
    } else if (val === 'top-right') {
      values = {
        top: '0px',
        left: '',
        right: '0px',
        bottom: '',
        transform: ''
      }
    } else if (val === 'left-middle') {
      values = {
        top: '50%',
        left: '0px',
        right: '',
        bottom: '',
        transform: 'translateY(-50%)'
      }
    } else if (val === 'right-middle') {
      values = {
        top: '50%',
        left: '',
        right: '0px',
        bottom: '',
        transform: 'translateY(-50%)'
      }
    } else if (val === 'bottom-left') {
      values = {
        top: '',
        left: '0px',
        right: '',
        bottom: '0px',
        transform: ''
      }
    } else if (val === 'bottom-right') {
      values = {
        top: '',
        left: '',
        right: '0px',
        bottom: '0px',
        transform: ''
      }
    } else if (val === 'bottom') {
      values = {
        top: '',
        left: '50%',
        right: '',
        bottom: '0px',
        transform: 'translateX(-50%)'
      }
    } else if (val === 'middle') {
      values = {
        top: '50%',
        left: '50%',
        right: '',
        bottom: '',
        transform: 'translate(-50%, -50%)'
      }
    }
    this.props.form.setFieldsValue(values)
  }
  render() {
    const { wrap } = this.props
    const { getFieldDecorator } = this.props.form
@@ -138,7 +216,7 @@
                </Tooltip>
              }>
                {getFieldDecorator('datatype', {
                  initialValue: wrap.datatype || 'dynamic'
                  initialValue: wrap.datatype
                })(
                  <Radio.Group>
                    <Radio value="dynamic">动态</Radio>
@@ -180,6 +258,18 @@
                )}
              </Form.Item>
            </Col> : null}
            {linkType === 'sup' ? <Col span={12}>
              <Form.Item label="显示控制">
                {getFieldDecorator('supControl', {
                  initialValue: wrap.supControl || 'show'
                })(
                  <Radio.Group>
                    <Radio key="hidden" value="hidden"> 选行显示 </Radio>
                    <Radio key="show" value="show"> 始终显示 </Radio>
                  </Radio.Group>
                )}
              </Form.Item>
            </Col> : null}
            {linkType === 'sync' ? <Col span={12}>
              <Form.Item label="同步组件">
                {getFieldDecorator('syncModule', {
@@ -196,7 +286,12 @@
              </Form.Item>
            </Col> : null}
            {linkType === 'sync' ? <Col span={12}>
              <Form.Item label="全选">
              <Form.Item label={
                <Tooltip placement="topLeft" title="当同步组件可多选时,设置全选有效。">
                  <Icon type="question-circle" />
                  全选
                </Tooltip>
              }>
                {getFieldDecorator('checkAll', {
                  initialValue: wrap.checkAll || 'hidden'
                })(
@@ -224,6 +319,21 @@
                )}
              </Form.Item>
            </Col>
            {position === 'fixed' ? <Col span={12}>
              <Form.Item label="快捷选择">
                <Select onSelect={this.chose}>
                  <Select.Option key='1' value={'top'}>上</Select.Option>
                  <Select.Option key='2' value={'top-left'}>左上</Select.Option>
                  <Select.Option key='3' value={'top-right'}>右上</Select.Option>
                  <Select.Option key='4' value={'left-middle'}>左中</Select.Option>
                  <Select.Option key='5' value={'right-middle'}>右中</Select.Option>
                  <Select.Option key='6' value={'bottom-left'}>左下</Select.Option>
                  <Select.Option key='7' value={'bottom-right'}>右下</Select.Option>
                  <Select.Option key='8' value={'bottom'}>下</Select.Option>
                  <Select.Option key='9' value={'middle'}>中间</Select.Option>
                </Select>
              </Form.Item>
            </Col> : null}
            {position === 'fixed' ? <Col span={12}>
              <Form.Item label="距上">
                {getFieldDecorator('top', {
@@ -268,8 +378,12 @@
                    <Select.Option key='1' value={''}>无</Select.Option>
                    <Select.Option key='2' value={'translateY(-50%)'}>上移50%</Select.Option>
                    <Select.Option key='3' value={'translateY(50%)'}>下移50%</Select.Option>
                    <Select.Option key='5' value={'translateX(-50%)'}>左移50%</Select.Option>
                    <Select.Option key='4' value={'translateX(50%)'}>右移50%</Select.Option>
                    <Select.Option key='4' value={'translateX(-50%)'}>左移50%</Select.Option>
                    <Select.Option key='5' value={'translateX(50%)'}>右移50%</Select.Option>
                    <Select.Option key='6' value={'translate(-50%, -50%)'}>左上移50%</Select.Option>
                    <Select.Option key='7' value={'translate(-50%, 50%)'}>左下移50%</Select.Option>
                    <Select.Option key='8' value={'translate(50%, -50%)'}>右上移50%</Select.Option>
                    <Select.Option key='9' value={'translate(50%, 50%)'}>右下移50%</Select.Option>
                  </Select>
                )}
              </Form.Item>
src/menu/components/card/cardcellcomponent/index.jsx
@@ -626,7 +626,7 @@
        >
          <ActionForm
            dict={dict}
            type="card"
            type={cards.type === 'balcony' ? '' : 'card'}
            card={card}
            formlist={this.state.formlist}
            inputSubmit={this.handleActionSubmit}
src/menu/components/share/styleInput/index.jsx
@@ -24,14 +24,8 @@
  UNSAFE_componentWillMount () {
    const { value, options } = this.props
    let val = ''
    let unit = ''
    if (value !== undefined) {
      val = value
    }
    unit = options[0]
    let val = value || ''
    let unit = options[0]
    if (val) {
      if (val.indexOf('px') > -1) {
@@ -56,6 +50,35 @@
  shouldComponentUpdate (nextProps, nextState) {
    return !is(fromJS(this.state), fromJS(nextState))
  }
  UNSAFE_componentWillReceiveProps(nextProps) {
    if (!nextProps.value && this.state.value !== '') {
      this.setState({value: ''})
    } else if (nextProps.value && nextProps.value !== `${this.state.value}${this.state.unit}`) {
      let val = nextProps.value
      let unit = this.state.unit
      if (val) {
        if (val.indexOf('px') > -1) {
          unit = 'px'
        } else if (val.indexOf('%') > -1) {
          unit = '%'
        } else if (val.indexOf('vw') > -1) {
          unit = 'vw'
        } else if (val.indexOf('vh') > -1) {
          unit = 'vh'
        }
      }
      let _val = parseFloat(val)
      if (isNaN(_val)) {
        _val = ''
      }
      this.setState({value: _val, unit})
    }
  }
  /**
@@ -85,16 +108,17 @@
    this.setState({
      value: _val,
    }, () => {
      this.props.onChange(_val ? `${_val}${unit}` : '')
    })
    this.props.onChange(_val ? `${_val}${unit}` : '')
  }
  changeUnit = (val) => {
    const { value } = this.state
    this.setState({unit: val})
    this.props.onChange(value ? `${value}${val}` : '')
    this.setState({unit: val}, () => {
      this.props.onChange(value ? `${value}${val}` : '')
    })
  }
  render () {
src/mob/mobshell/card.jsx
@@ -24,6 +24,7 @@
const NormalNavbar = asyncComponent(() => import('@/mob/components/navbar/normal-navbar'))
const NormalTopbar = asyncComponent(() => import('@/mob/components/topbar/normal-navbar'))
const NormalMenuBar = asyncComponent(() => import('@/mob/components/menubar/normal-menubar'))
const Balcony = asyncComponent(() => import('@/menu/components/card/balcony'))
const Card = ({ id, card, moveCard, findCard, delCard, updateConfig }) => {
  const originalIndex = findCard(id).index
@@ -116,6 +117,8 @@
      return (<NormalTopbar card={card} updateConfig={updateConfig} deletecomponent={delCard}/>)
    } else if (card.type === 'menubar') {
      return (<NormalMenuBar card={card} updateConfig={updateConfig} deletecomponent={delCard}/>)
    } else if (card.type === 'balcony') {
      return (<Balcony card={card} updateConfig={updateConfig} deletecomponent={delCard}/>)
    }
  }
src/mob/modulesource/option.jsx
@@ -33,6 +33,7 @@
  { type: 'menu', url: Mainsearch, component: 'search', subtype: 'mainsearch', title: '搜索条件', width: 24 },
  { type: 'menu', url: card1, component: 'card', subtype: 'datacard', title: '数据卡', width: 24 },
  { type: 'menu', url: card2, component: 'card', subtype: 'propcard', title: '属性卡', width: 24 },
  { type: 'menu', url: card2, component: 'balcony', subtype: 'balcony', title: '可浮动卡', width: 24 },
  { type: 'menu', url: form, component: 'form', subtype: 'stepform', title: '表单', width: 24 },
  { type: 'menu', url: Carousel, component: 'carousel', subtype: 'datacard', title: '轮播-动态数据', width: 24 },
  { type: 'menu', url: Carousel1, component: 'carousel', subtype: 'propcard', title: '轮播-静态数据', width: 24 },
src/pc/menushell/card.jsx
@@ -23,6 +23,7 @@
const NormalLogin = asyncComponent(() => import('@/pc/components/login/normal-login'))
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 Card = ({ id, card, moveCard, findCard, delCard, updateConfig }) => {
  const originalIndex = findCard(id).index
@@ -112,6 +113,8 @@
      return (<CodeSandbox card={card} updateConfig={updateConfig} deletecomponent={delCard}/>)
    } else if (card.type === 'login') {
      return (<NormalLogin card={card} updateConfig={updateConfig} deletecomponent={delCard}/>)
    } else if (card.type === 'balcony') {
      return (<Balcony card={card} updateConfig={updateConfig} deletecomponent={delCard}/>)
    }
  }
src/pc/modulesource/option.jsx
@@ -32,6 +32,7 @@
  { type: 'menu', url: Mainsearch, component: 'search', subtype: 'mainsearch', title: '搜索条件', width: 24 },
  { type: 'menu', url: card1, component: 'card', subtype: 'datacard', title: '数据卡', width: 24 },
  { type: 'menu', url: card2, component: 'card', subtype: 'propcard', title: '属性卡', width: 24 },
  { type: 'menu', url: card2, component: 'balcony', subtype: 'balcony', title: '可浮动卡', width: 24 },
  { type: 'menu', url: form, component: 'form', subtype: 'stepform', title: '表单', width: 24 },
  { type: 'menu', url: Carousel, component: 'carousel', subtype: 'datacard', title: '轮播-动态数据', width: 24 },
  { type: 'menu', url: Carousel1, component: 'carousel', subtype: 'propcard', title: '轮播-静态数据', width: 24 },
src/tabviews/custom/components/card/balcony/index.jsx
New file
@@ -0,0 +1,301 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import { is, fromJS } from 'immutable'
import { Spin, notification } from 'antd'
import Api from '@/api'
// import Utils from '@/utils/utils.js'
import UtilsDM from '@/utils/utils-datamanage.js'
import asyncComponent from '@/utils/asyncComponent'
import MKEmitter from '@/utils/events.js'
import './index.scss'
const CardCellComponent = asyncComponent(() => import('../cardcellList'))
class BalconyComponent extends Component {
  static propTpyes = {
    BID: PropTypes.any,
    menu: PropTypes.object,
    data: PropTypes.array,
    config: PropTypes.object,
    menuType: PropTypes.any,
  }
  state = {
    BID: '',
    config: null,
    syncConfig: null,
    loading: false,
    sync: false,
    data: {},
    show: true
  }
  UNSAFE_componentWillMount () {
    const { data, BID, menu } = this.props
    let _config = fromJS(this.props.config).toJS()
    let _cols = new Map()
    let _data = {}
    let _sync = false
    if (_config.setting && _config.wrap.datatype !== 'static') {
      _sync = _config.setting.sync === 'true'
      if (_sync && data) {
        _data = data[_config.dataName] || {}
        if (_data && Array.isArray(_data)) {
          _data = _data[0] || {}
        }
        _sync = false
      }
    } else {
      _data = {}
    }
    if (_data) {
      _data.$$BID = BID || ''
    }
    _config.columns.forEach(item => {
      _cols.set(item.field, item)
    })
    if (_config.wrap.position === 'fixed') {
      _config.style.position = 'fixed'
      _config.style.zIndex = 2
      _config.style.left = _config.wrap.left || ''
      _config.style.right = _config.wrap.right || ''
      _config.style.top = _config.wrap.top || ''
      _config.style.bottom = _config.wrap.bottom || ''
      _config.style.transform = _config.wrap.transform || ''
      _config.style.width = _config.wrap.realwidth || ''
    }
    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
            }
          }
        })
      }
      filterComponent(menu.components)
      _config.elements = _config.elements.map(item => {
        if (item.eleType === 'button') {
          item.$syncModule = _config.wrap.syncModule
        }
        return item
      })
    } else if (_config.wrap.linkType === 'sup') {
      _config.wrap.supModule = _config.wrap.supModule.pop()
      if (_config.wrap.supControl === 'hidden') {
        show = false
      }
    }
    this.setState({
      show,
      syncConfig,
      sync: _sync,
      data: _data,
      BID: BID || '',
      config: _config,
      arr_field: _config.columns.map(col => col.field).join(','),
    }, () => {
      if (_config.wrap.datatype !== 'static' && _config.setting && _config.setting.sync !== 'true' && _config.setting.onload === 'true') {
        this.loadData()
      }
    })
  }
  componentDidMount () {
    MKEmitter.addListener('reloadData', this.reloadData)
    MKEmitter.addListener('resetSelectLine', this.resetParentParam)
    MKEmitter.addListener('refreshByButtonResult', this.refreshByButtonResult)
  }
  shouldComponentUpdate (nextProps, nextState) {
    return !is(fromJS(this.state), fromJS(nextState))
  }
  componentWillUnmount () {
    this.setState = () => {
      return
    }
    MKEmitter.removeListener('reloadData', this.reloadData)
    MKEmitter.removeListener('resetSelectLine', this.resetParentParam)
    MKEmitter.removeListener('refreshByButtonResult', this.refreshByButtonResult)
  }
  /**
   * @description 图表数据更新,刷新内容
   */
  UNSAFE_componentWillReceiveProps (nextProps) {
    const { sync, config, BID } = this.state
    if (sync && !is(fromJS(this.props.data), fromJS(nextProps.data))) {
      let _data = {}
      if (nextProps.data && nextProps.data[config.dataName]) {
        _data = nextProps.data[config.dataName]
        if (_data && Array.isArray(_data)) {
          _data = _data[0]
        }
      }
      if (_data) {
        _data.$$BID = BID || ''
      }
      this.setState({sync: false, data: _data})
    }
  }
  /**
   * @description 按钮执行完成后页面刷新
   * @param {*} menuId     // 菜单Id
   * @param {*} position   // 刷新位置
   * @param {*} btn        // 执行的按钮
   */
  refreshByButtonResult = (menuId, position, btn) => {
    const { config, BID, syncConfig } = this.state
    if (config.uuid !== menuId) return
    this.loadData()                                                            // 数据刷新
    let supModule = config.wrap.supModule
    if (syncConfig) {
      supModule = syncConfig.setting.supModule
      MKEmitter.emit('refreshByButtonResult', syncConfig.uuid, position, btn)
    }
    if (btn.syncComponentId && btn.syncComponentId !== config.uuid && btn.syncComponentId !== supModule) {
      MKEmitter.emit('reloadData', btn.syncComponentId)                        // 同级标签刷新
    }
    if (position === 'mainline' && supModule) {                 // 主表行刷新
      MKEmitter.emit('reloadData', supModule, (BID || 'empty'))
    } else if (position === 'popclose') {                                      // 标签关闭刷新
      supModule && MKEmitter.emit('reloadData', supModule, (BID || 'empty'))
      btn.$tabId && MKEmitter.emit('refreshPopButton', btn.$tabId)
    }
  }
  resetParentParam = (MenuID, id) => {
    const { config, syncConfig } = this.state
    if (syncConfig) {
      if (!syncConfig.setting.supModule || syncConfig.setting.supModule !== MenuID) return
      if (id !== this.state.BID) {
        this.setState({ BID: id }, () => {
          this.loadData()
        })
      }
    } else {
      if (!config.wrap.supModule || config.wrap.supModule !== MenuID) return
      if (config.wrap.supControl === 'hidden') {
        this.setState({ show: id ? true : false })
      }
      if (id !== this.state.BID) {
        this.setState({ BID: id }, () => {
          this.loadData()
        })
      }
    }
  }
  reloadData = (menuId) => {
    const { config } = this.state
    if (menuId !== config.uuid) return
    this.loadData()
  }
  async loadData () {
    const { menuType } = this.props
    const { config, arr_field, BID } = this.state
    if (config.wrap.datatype === 'static') {
      this.setState({
        data: {$$BID: BID || ''},
      })
      return
    } else if (config.setting.supModule && !BID) { // BID 不存在时,不做查询
      this.setState({
        data: {$$BID: BID || ''},
      })
      return
    }
    let searches = []
    this.setState({
      loading: true
    })
    let _orderBy = config.setting.order || ''
    let param = UtilsDM.getQueryDataParams(config.setting, arr_field, searches, _orderBy, 1, 1, BID, menuType)
    let result = await Api.genericInterface(param)
    if (result.status) {
      let _data = result.data && result.data[0] ? result.data[0] : {}
      _data.$$BID = BID || ''
      this.setState({
        data: _data,
        loading: false
      })
    } else {
      this.setState({
        loading: false,
      })
      notification.error({
        top: 92,
        message: result.message,
        duration: 10
      })
    }
  }
  render() {
    const { config, loading, data, show, syncConfig } = this.state
    return (
      <div className={'custom-balcony-box' + (!show ? ' hidden' : '')} style={config.style}>
        {loading ?
          <div className="loading-mask">
            <div className="ant-spin-blur"></div>
            <Spin />
          </div> : null
        }
        <CardCellComponent data={data} cards={syncConfig || config} cardCell={config} elements={config.elements}/>
      </div>
    )
  }
}
export default BalconyComponent
src/tabviews/custom/components/card/balcony/index.scss
New file
@@ -0,0 +1,65 @@
.custom-balcony-box {
  background: #ffffff;
  background-position: center center;
  background-repeat: no-repeat;
  background-size: cover;
  position: relative;
  .card-row-list::after {
    content: ' ';
    display: block;
    clear: both;
  }
  .card-row-list {
    .card-item-box {
      background-color: #ffffff;
      transition: all 0.3s;
    }
    >.pointer {
      cursor: pointer;
    }
    >.active >.card-item-box {
      border-color: #1890ff!important;
      box-shadow: 0 0 4px #1890ff;
    }
  }
  .card-item-box {
    position: relative;
    background-position: center center;
    background-repeat: no-repeat;
    background-size: cover;
    transition: all 0.3s;
  }
  .loading-mask {
    position: absolute;
    left: 40px;
    top: 0;
    right: 40px;
    bottom: 0px;
    display: flex;
    align-items: center;
    justify-content: center;
    text-align: justify;
    z-index: 1;
    .ant-spin-blur {
      position: absolute;
      width: 100%;
      height: 100%;
      opacity: 0.5;
      background: #ffffff;
    }
  }
}
.custom-balcony-box.hidden {
  display: none;
}
.custom-balcony-box::after {
  content: ' ';
  display: block;
  clear: both;
}
src/tabviews/custom/components/card/data-card/index.jsx
@@ -146,6 +146,7 @@
  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)
@@ -185,9 +186,18 @@
      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)
  }
  getSyncData = (syncModule, btnId) => {
    const { config, selectedData } = this.state
    if (config.uuid !== syncModule) return
    MKEmitter.emit('triggerBtnId', btnId, (selectedData || []))
  }
  /**
@@ -220,20 +230,6 @@
    } else if (position === 'popclose') {                                      // 标签关闭刷新
      config.setting.supModule && MKEmitter.emit('reloadData', config.setting.supModule, (BID || 'empty'))
      btn.$tabId && MKEmitter.emit('refreshPopButton', btn.$tabId)
    }
  }
  reloadData = (btn) => {
    if (!btn || btn.resetPageIndex !== 'false') {
      this.setState({
        pageIndex: 1
      }, () => {
        this.loadmaindata(true, 'true')
        this.getStatFieldsValue()
      })
    } else {
      this.loadmaindata(true, 'false')
      this.getStatFieldsValue()
    }
  }
@@ -302,6 +298,7 @@
        total: 0,
        loading: false
      })
      MKEmitter.emit('resetSelectLine', config.uuid, '', '')
      return
    }
@@ -348,6 +345,7 @@
        total: result.total,
        loading: false
      })
      MKEmitter.emit('resetSelectLine', config.uuid, '', '')
    } else {
      this.setState({
        loading: false
src/tabviews/custom/components/table/normal-table/index.jsx
@@ -501,6 +501,14 @@
    }
  }
  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
@@ -531,6 +539,7 @@
  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)
@@ -544,6 +553,7 @@
      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
@@ -35,6 +35,7 @@
const BraftEditor = asyncComponent(() => import('./components/editor/braft-editor'))
const SandBox = asyncComponent(() => import('./components/code/sand-box'))
const NormalTree = asyncComponent(() => import('./components/tree/antd-tree'))
const Balcony = asyncComponent(() => import('./components/card/balcony'))
const SettingComponent = asyncComponent(() => import('@/tabviews/zshare/settingcomponent'))
const PagemsgComponent = asyncComponent(() => import('@/tabviews/zshare/pageMessage'))
@@ -551,7 +552,7 @@
        item.action = item.action.filter(cell => {
          cell.logLabel = item.name + '-' + cell.label
          cell.ContainerId = this.state.ContainerId
          cell.syncComponentId = cell.syncComponent ? cell.syncComponent.pop() : ''
          cell.syncComponentId = cell.syncComponent ? (cell.syncComponent.pop() || '') : ''
          cell.$menuId = item.uuid
          cell.$tabId = tabId
          cell.$view = 'CustomPage'
@@ -583,7 +584,7 @@
              cell.logLabel = item.name + '-' + cell.label
              cell.Ot = 'requiredSgl'
              cell.ContainerId = this.state.ContainerId
              cell.syncComponentId = cell.syncComponent ? cell.syncComponent.pop() : ''
              cell.syncComponentId = cell.syncComponent ? (cell.syncComponent.pop() || '') : ''
              cell.$menuId = item.uuid
              cell.$tabId = tabId
              cell.$view = 'CustomPage'
@@ -606,7 +607,7 @@
              cell.logLabel = item.name + '-' + cell.label
              cell.Ot = 'requiredSgl'
              cell.ContainerId = this.state.ContainerId
              cell.syncComponentId = cell.syncComponent ? cell.syncComponent.pop() : ''
              cell.syncComponentId = cell.syncComponent ? (cell.syncComponent.pop() || '') : ''
              cell.$menuId = item.uuid
              cell.$tabId = tabId
              cell.$view = 'CustomPage'
@@ -624,6 +625,25 @@
            return cell.eleType !== 'button' || isHS || permAction[cell.uuid]
          })
        })
      } else if (item.type === 'balcony') {
        item.elements = item.elements.filter(cell => {
          if (cell.eleType === 'button') {
            cell.logLabel = item.name + '-' + cell.label
            cell.ContainerId = this.state.ContainerId
            cell.syncComponentId = cell.syncComponent ? (cell.syncComponent.pop() || '') : ''
            cell.$menuId = item.uuid
            cell.$tabId = tabId
            cell.$view = 'CustomPage'
            if (cell.OpenType === 'funcbutton' && cell.funcType === 'print' && cell.verify) { // 打印机设置
              cell = this.getPrinter(cell, item.uuid)
            }
          } else if (['text', 'number', 'link'].includes(cell.eleType) && !cell.height) {
            cell.innerHeight = 'auto'
          }
          return cell.eleType !== 'button' || isHS || permAction[cell.uuid]
        })
      } else if ((item.type === 'table' && item.subtype === 'tablecard') || item.type === 'carousel') {
        item.subcards && item.subcards.forEach(card => {
          let _hasheight = card.style.height && card.style.height !== 'auto'
@@ -632,7 +652,7 @@
              cell.logLabel = item.name + '-' + cell.label
              cell.Ot = 'requiredSgl'
              cell.ContainerId = this.state.ContainerId
              cell.syncComponentId = cell.syncComponent ? cell.syncComponent.pop() : ''
              cell.syncComponentId = cell.syncComponent ? (cell.syncComponent.pop() || '') : ''
              cell.$menuId = item.uuid
              cell.$tabId = tabId
              cell.$view = 'CustomPage'
@@ -658,7 +678,7 @@
            cell.logLabel = item.name + '-' + cell.label
            cell.Ot = 'requiredSgl'
            cell.ContainerId = this.state.ContainerId
            cell.syncComponentId = cell.syncComponent ? cell.syncComponent.pop() : ''
            cell.syncComponentId = cell.syncComponent ? (cell.syncComponent.pop() || '') : ''
            cell.$menuId = item.uuid
            cell.$tabId = tabId
            cell.$view = 'CustomPage'
@@ -1098,6 +1118,12 @@
            <PropCard 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 menu={config} config={item} data={data} BID={_bid} menuType={menuType} />
          </Col>
        )
      } else if (item.type === 'carousel' && item.subtype === 'datacard') {
        return (
          <Col span={item.width} key={item.uuid}>
src/tabviews/zshare/actionList/normalbutton/index.jsx
@@ -70,9 +70,8 @@
  componentDidMount () {
    const { position } = this.props
    if (position === 'toolbar') {
      MKEmitter.addListener('triggerBtnId', this.actionTrigger)
    } else if (position === 'form') {
    MKEmitter.addListener('triggerBtnId', this.actionTrigger)
    if (position === 'form') {
      MKEmitter.addListener('triggerFormSubmit', this.actionSubmit)
    }
    MKEmitter.addListener('returnModuleParam', this.resetModuleParam)
@@ -159,6 +158,11 @@
      return
    }
    if (btn.$syncModule && !triggerId) {
      MKEmitter.emit('getSyncData', btn.$syncModule, btn.uuid)
      return
    }
    let _this = this
    let data = record || selectedData || []
src/views/menudesign/index.jsx
@@ -397,6 +397,13 @@
              _sort++
            })
          })
        } else if (item.type === 'balcony') {
          item.elements && item.elements.forEach(cell => {
            if (cell.eleType !== 'button') return
            this.checkBtn(cell)
            buttons.push(`select '${cell.uuid}' as menuid, '${item.name + '-' + cell.label}' as menuname, '${_sort * 10}' as Sort`)
            _sort++
          })
        } else if (item.type === 'line' || item.type === 'bar') {
          item.action && item.action.forEach(btn => {
            this.checkBtn(btn)
@@ -846,6 +853,7 @@
          return
        }
        if (['propcard', 'brafteditor', 'sandbox', 'stepform'].includes(item.subtype) && item.wrap.datatype === 'static') return
        if (['balcony'].includes(item.type) && item.wrap.datatype === 'static') return
  
        if (item.setting) {
          if (item.setting.interType === 'system' && item.setting.execute !== 'false' && !item.setting.dataresource) {
src/views/mobdesign/index.jsx
@@ -722,6 +722,22 @@
              _sort++
            })
          })
        } else if (item.type === 'carousel') {
          item.subcards.forEach(card => {
            card.elements && card.elements.forEach(cell => {
              if (cell.eleType !== 'button') return
              this.checkBtn(cell)
              buttons.push(`select '${cell.uuid}' as menuid, '${item.name + '-' + cell.label}' as menuname, '${_sort * 10}' as Sort`)
              _sort++
            })
          })
        } else if (item.type === 'balcony') {
          item.elements && item.elements.forEach(cell => {
            if (cell.eleType !== 'button') return
            this.checkBtn(cell)
            buttons.push(`select '${cell.uuid}' as menuid, '${item.name + '-' + cell.label}' as menuname, '${_sort * 10}' as Sort`)
            _sort++
          })
        } else if (item.type === 'line' || item.type === 'bar') {
          item.action && item.action.forEach(btn => {
            this.checkBtn(btn)
@@ -1315,7 +1331,8 @@
        }
        if (['propcard', 'brafteditor', 'sandbox', 'tabbar', 'stepform'].includes(item.subtype) && item.wrap.datatype === 'static') return
        if (['balcony'].includes(item.type) && item.wrap.datatype === 'static') return
        if (item.setting) {
          if (item.setting.interType === 'system' && item.setting.execute !== 'false' && !item.setting.dataresource) {
            error = `组件《${item.name}》未设置数据源!`
src/views/pcdesign/index.jsx
@@ -747,6 +747,22 @@
              _sort++
            })
          })
        } else if (item.type === 'carousel') {
          item.subcards.forEach(card => {
            card.elements && card.elements.forEach(cell => {
              if (cell.eleType !== 'button') return
              this.checkBtn(cell)
              buttons.push(`select '${cell.uuid}' as menuid, '${item.name + '-' + cell.label}' as menuname, '${_sort * 10}' as Sort`)
              _sort++
            })
          })
        } else if (item.type === 'balcony') {
          item.elements && item.elements.forEach(cell => {
            if (cell.eleType !== 'button') return
            this.checkBtn(cell)
            buttons.push(`select '${cell.uuid}' as menuid, '${item.name + '-' + cell.label}' as menuname, '${_sort * 10}' as Sort`)
            _sort++
          })
        } else if (item.type === 'line' || item.type === 'bar') {
          item.action && item.action.forEach(btn => {
            this.checkBtn(btn)
@@ -1338,7 +1354,8 @@
          return
        }
        if (['propcard', 'brafteditor', 'sandbox', 'stepform'].includes(item.subtype) && item.wrap.datatype === 'static') return
        if (['balcony'].includes(item.type) && item.wrap.datatype === 'static') return
        if (item.setting) {
          if (item.setting.interType === 'system' && item.setting.execute !== 'false' && !item.setting.dataresource) {
            error = `组件《${item.name}》未设置数据源!`