king
2022-07-12 88756147643a1d4ffb840797b96ea44462b0551d
2022-07-12
5 文件已重命名
2 文件已复制
23个文件已修改
4个文件已添加
908 ■■■■■ 已修改文件
src/assets/mobimg/simple-form.png 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/form/simple-form/index.jsx 309 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/form/simple-form/index.scss 88 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/form/simple-form/options.jsx 174 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/form/step-form/index.jsx 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/form/step-form/index.scss 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/form/step-form/options.jsx 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/form/tab-form/index.jsx 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/group/groupcomponents/card.jsx 7 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/group/paste/index.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/share/normalheader/index.jsx 7 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/share/normalheader/index.scss 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/share/searchcomponent/index.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/tabs/paste/index.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/tabs/tabcomponents/card.jsx 7 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/menushell/card.jsx 7 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/modulesource/option.jsx 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/pastecontroller/index.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/mob/components/tabs/tabcomponents/card.jsx 7 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/mob/mobshell/card.jsx 7 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/mob/modulesource/option.jsx 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pc/menushell/card.jsx 7 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/form/simple-form/index.jsx 133 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/form/simple-form/index.scss 53 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/form/step-form/index.jsx 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/form/step-form/index.scss 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/group/normal-group/index.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/share/normalheader/index.scss 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/share/tabtransfer/index.jsx 11 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/tree/antd-tree/index.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/tree/antd-tree/index.scss 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/index.jsx 11 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mobdesign/index.jsx 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/pcdesign/index.jsx 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/mobimg/simple-form.png
src/menu/components/form/simple-form/index.jsx
copy from src/menu/components/form/normal-form/index.jsx copy to src/menu/components/form/simple-form/index.jsx
File was copied from src/menu/components/form/normal-form/index.jsx
@@ -18,12 +18,12 @@
import './index.scss'
const ModalForm = asyncComponent(() => import('@/templates/zshare/modalform'))
const NormalForm = asyncIconComponent(() => import('@/components/normalform'))
const SettingComponent = asyncIconComponent(() => import('@/menu/datasource'))
const NormalForm = asyncIconComponent(() => import('@/components/normalform'))
const CardComponent = asyncComponent(() => import('@/templates/modalconfig/dragelement'))
const MobCardComponent = asyncComponent(() => import('@/mob/components/formdragelement'))
const FormTitle = asyncComponent(() => import('../dragtitle'))
const FormAction = asyncComponent(() => import('../formaction'))
const NormalHeader = asyncComponent(() => import('@/menu/components/share/normalheader'))
const CopyComponent = asyncIconComponent(() => import('@/menu/components/share/copycomponent'))
const PasteComponent = asyncIconComponent(() => import('@/menu/components/share/pastecomponent'))
const UserComponent = asyncIconComponent(() => import('@/menu/components/share/usercomponent'))
@@ -31,7 +31,7 @@
const { confirm } = Modal
class PropCardEditComponent extends Component {
class SimpleFormComponent extends Component {
  static propTpyes = {
    card: PropTypes.object,
    deletecomponent: PropTypes.func,
@@ -43,7 +43,6 @@
    appType: sessionStorage.getItem('appType'),
    card: null,
    back: false,
    group: null,
    showField: false,
    visible: false,
    editform: null,
@@ -68,20 +67,18 @@
        width: card.width || 24,
        name: card.name,
        subtype: card.subtype,
        setting: { },
        wrap: { name: card.name, width: card.width || 24, datatype: 'static', groupLabel: 'show', color: '#1890ff' },
        setting: { interType: 'system' },
        wrap: { name: card.name, width: card.width || 24, datatype: 'static' },
        style: { marginLeft: '0px', marginRight: '0px', marginTop: '8px', marginBottom: '8px' },
        headerStyle: { fontSize: '16px', borderBottomWidth: '1px', borderBottomColor: '#e8e8e8' },
        columns: [],
        scripts: [],
        subcards: [{
          uuid: Utils.getuuid(),
          setting: {title: '第一步', align: 'left_right'},
          sort: 1,
          setting: {title: '空', align: 'left_right', enable: 'true'},
          style: {},
          fields: [],
          prevButton: {label: '上一步', type: 'prev', enable: 'false', style: {marginRight: '15px', paddingTop: '5px', paddingBottom: '5px'}},
          subButton: {label: '提交', type: 'submit', intertype: 'system', reload: 'false', sqlType: 'update', sql: '', Ot: 'notRequired', execSuccess: 'never', enable: 'true', style: {backgroundColor: '#1890ff', color: '#ffffff', paddingLeft: '25px', paddingRight: '25px', paddingTop: '5px', paddingBottom: '5px'}},
          nextButton: {label: '跳过', type: 'next', enable: 'false', style: {paddingTop: '5px', paddingBottom: '5px'}}
        }]
      }
@@ -105,15 +102,11 @@
          return scard
        })
      }
      this.setState({
        group: _card.subcards[0] || null
      })
      this.updateComponent(_card)
    } else {
      let _card = fromJS(card).toJS()
      this.setState({
        card: _card,
        group: _card.subcards[0] || null
        card: _card
      })
    }
  }
@@ -184,9 +177,9 @@
      card.subcards.forEach(item => {
        item.fields.forEach(m => {
          if (m.type === 'linkMain' && !supModule) {
            card.errors.push({ level: 1, detail: `分组“${item.setting.title}”中关联主表表单“${m.label}”无效`})
            card.errors.push({ level: 1, detail: `关联主表表单“${m.label}”无效`})
          } else if (m.field && !columns.includes(m.field) && lowcols.includes(m.field.toLowerCase())) {
            card.errors.push({ level: 1, detail: `分组“${item.setting.title}”中表单“${m.label}”大小写与字段集不一致`})
            card.errors.push({ level: 1, detail: `表单“${m.label}”大小写与字段集不一致`})
          }
        })
      })
@@ -196,7 +189,7 @@
      card.subcards.forEach(item => {
        item.fields.forEach(m => {
          if (m.type === 'linkMain' && !supModule) {
            card.errors.push({ level: 1, detail: `分组“${item.setting.title}”中关联主表表单“${m.label}”无效`})
            card.errors.push({ level: 1, detail: `关联主表表单“${m.label}”无效`})
          }
        })
      })
@@ -230,18 +223,18 @@
  }
  getStyle = (comIds, style) => {
    const { card, group } = this.state
    const { card } = this.state
    if (comIds[0] === 'form') {
      let Index = group.fields.findIndex(n => n.uuid === comIds[1])
      let Index = card.subcards[0].fields.findIndex(n => n.uuid === comIds[1])
      if (Index === -1) return
      
      let _group = fromJS(group).toJS()
      let _card = fromJS(card).toJS()
      _group.fields[Index].style = style
      _card.subcards[0].fields[Index].style = style
      this.updateGroup(_group)
      this.updateComponent(_card)
      return
    }
@@ -249,102 +242,33 @@
    if (comIds.length !== 1 || comIds[0] !== card.uuid) return
    let _card = {...card, style}
    this.updateComponent(_card)
  }
  addCard = () => {
  updateGroup = (res) => {
    let card = fromJS(this.state.card).toJS()
    let newcard = {
      uuid: Utils.getuuid(),
      setting: { title: `第${card.subcards.length + 1}步`, align: 'left_right' },
      sort: card.subcards.length + 1,
      style: {},
      fields: [],
      prevButton: {label: '上一步', type: 'prev', enable: 'false', style: {marginRight: '15px', paddingTop: '5px', paddingBottom: '5px'}},
      subButton: {label: '提交', type: 'submit', intertype: 'system', reload: 'false', sqlType: 'update', sql: '', Ot: 'notRequired', enable: 'true', style: {backgroundColor: '#1890ff', color: '#ffffff', paddingLeft: '25px', paddingRight: '25px', paddingTop: '5px', paddingBottom: '5px'}},
      nextButton: {label: '跳过', type: 'next', enable: 'false', style: {paddingTop: '5px', paddingBottom: '5px'}}
    }
    card.subcards[0] = res
    card.subcards.push(newcard)
    this.setState({
      group: newcard
    })
    this.updateComponent(card)
  }
  changecards = (list) => {
    let card = fromJS(this.state.card).toJS()
    card.subcards = list.map((item, index) => {
      item.sort = index + 1
      return item
    })
    this.updateComponent(card)
  }
  selectGroup = (item) => {
    this.setState({
      group: item
    })
  }
  changeGroup = (item) => {
    this.updateGroup(item)
  }
  closeGroup = (cell) => {
    const { group } = this.state
    let card = fromJS(this.state.card).toJS()
    const _this = this
    confirm({
      content: '确定删除分组吗?',
      onOk() {
        card.subcards = card.subcards.filter(item => item.uuid !== cell.uuid)
        let _group = group
        if (group.uuid === cell.uuid) {
          _group = card.subcards[0] || null
        }
        _this.setState({group: _group})
        _this.updateComponent(card)
      },
      onCancel() {}
    })
  }
  updateGroup = (group) => {
    let card = fromJS(this.state.card).toJS()
    card.subcards = card.subcards.map(item => {
      if (item.uuid === group.uuid) {
        return group
      }
      return item
    })
    this.setState({group})
    this.updateComponent(card)
  }
  plusFields = (items) => {
    let _group = fromJS(this.state.group).toJS()
    const { card } = this.state
    _group.fields.push(...items)
    let _card = fromJS(card).toJS()
    this.updateGroup(_group)
    _card.subcards[0].fields.push(...items)
    this.updateComponent(_card)
  }
  changecols = (type) => {
    let card = fromJS(this.state.card).toJS()
    let config = fromJS(this.state.group).toJS()
    let _this = this
    config.fields = config.fields.map(item => {
    card.subcards[0].fields = card.subcards[0].fields.map(item => {
      item.labelwidth = 33.3
      item.span = 24
      if (['textarea','split','hint','checkcard','brafteditor'].includes(item.type)) {
@@ -368,13 +292,6 @@
    confirm({
      content: `确定切换为${type}列吗?`,
      onOk() {
        card.subcards = card.subcards.map(item => {
          if (item.uuid === config.uuid) {
            return config
          }
          return item
        })
        _this.setState({group: config})
        _this.updateComponent(card)
      },
      onCancel() {}
@@ -382,19 +299,11 @@
  }
  handleList = (list, newcard) => {
    let group = fromJS(this.state.group).toJS()
    let card = fromJS(this.state.card).toJS()
    group.fields = list
    card.subcards[0].fields = list
    card.subcards = card.subcards.map(item => {
      if (item.uuid === group.uuid) {
        return group
      }
      return item
    })
    this.setState({group}, () => {
    this.setState({}, () => {
      if (newcard) {
        this.handleForm(newcard)
      }
@@ -403,23 +312,14 @@
  }
  closeForm = (cell) => {
    let group = fromJS(this.state.group).toJS()
    let card = fromJS(this.state.card).toJS()
    let _this = this
    group.fields = group.fields.filter(item => item.uuid !== cell.uuid)
    card.subcards = card.subcards.map(item => {
      if (item.uuid === group.uuid) {
        return group
      }
      return item
    })
    card.subcards[0].fields = card.subcards[0].fields.filter(item => item.uuid !== cell.uuid)
    confirm({
      content: `确定删除<<${cell.label}>>吗?`,
      onOk() {
        _this.setState({group})
        _this.updateComponent(card)
      },
      onCancel() {}
@@ -428,8 +328,8 @@
  addForm = () => {
    const { appType } = this.state
    let group = fromJS(this.state.group).toJS()
    let lastItem = group.fields[group.fields.length - 1]
    let card = fromJS(this.state.card).toJS()
    let lastItem = card.subcards[0].fields[card.subcards[0].fields.length - 1]
    let span = appType === 'mob' ? 24 : 12
    if (lastItem && lastItem.span) {
      span = lastItem.span
@@ -453,26 +353,25 @@
      focus: true
    }
    group.fields.push(newcard)
    card.subcards[0].fields.push(newcard)
    this.setState({group}, () => {
    this.setState({card}, () => {
      this.handleForm(newcard)
    })
  }
  editModalCancel = () => {
    let group = fromJS(this.state.group).toJS()
    group.fields = group.fields.filter(item => !item.focus)
    let card = fromJS(this.state.card).toJS()
    card.subcards[0].fields = card.subcards[0].fields.filter(item => !item.focus)
    this.setState({group, visible: false, editform: null})
    this.updateGroup(group)
    this.setState({card, visible: false, editform: null})
  }
  /**
   * @description 表单编辑
   */
  handleForm = (_item) => {
    const { card, group, appType } = this.state
    const { card, appType } = this.state
    let _form = fromJS(_item).toJS()
    let _inputfields = []
    let _tabfields = []
@@ -487,7 +386,7 @@
    let _inputIndex = 1
    let _tabIndex = 1
    let _linkIndex = 1
    group.fields.forEach((item, i) => {
    card.subcards[0].fields.forEach((item, i) => {
      if (_form.uuid === item.uuid) {
        index = i
      }
@@ -504,8 +403,7 @@
        })
        _inputIndex++
      }
      if (_item.field !== item.field && item.hidden !== 'true' && ['text', 'number', 'select', 'link'].includes(item.type)) {
      if (_form.field !== item.field && item.hidden !== 'true' && ['text', 'number', 'select', 'link'].includes(item.type)) {
        _tabfields.push({
          field: item.field,
          label: _tabIndex + '、' + label
@@ -526,13 +424,14 @@
        uniq.set(item.field, true)
        _linkableFields.push({
          field: item.field,
          label: _linkIndex + '、' + item.label + ' (表单)'
          value: item.field,
          text: _linkIndex + '、' + item.label + ' (表单)'
        })
        _linksupFields.push({
          field: item.field,
          label: _linkIndex + '、' + label
          value: item.field,
          text: _linkIndex + '、' + label
        })
        _linkIndex++
      }
    })
@@ -541,9 +440,9 @@
    if (index !== null) {
      if (index === 0) {
        standardform = group.fields[index + 1] || null
        standardform = card.subcards[0].fields[index + 1] || null
      } else {
        standardform = group.fields[index - 1] || null
        standardform = card.subcards[0].fields[index - 1] || null
      }
    }
@@ -585,10 +484,10 @@
   */
  handleSubmit = () => {
    this.formRef.handleConfirm().then(res => {
      let _config = fromJS(this.state.group).toJS()
      let _config = fromJS(this.state.card).toJS()
      let fieldrepet = false // 字段重复
      _config.fields = _config.fields.map(item => {
      _config.subcards[0].fields = _config.subcards[0].fields.map(item => {
        if (item.uuid !== res.uuid && res.field && item.field && item.field.toLowerCase() === res.field.toLowerCase()) {
          fieldrepet = true
        }
@@ -640,7 +539,7 @@
              editform: null,
              visible: false
            })
            this.updateGroup(_config)
            this.updateComponent(_config)
          } else {
            this.setState({sqlVerifing: false})
            
@@ -654,48 +553,44 @@
          editform: null,
          visible: false
        })
        this.updateGroup(_config)
        this.updateComponent(_config)
      }
    })
  }
  pasteForm = (res) => {
    let _config = fromJS(this.state.card).toJS()
    if (res.subButton) {
      let card = fromJS(this.state.card).toJS()
      let _this = this
      res.uuid = Utils.getuuid()
      res.sort = card.subcards.length + 1
      _config.subcards[0].setting.focus = res.focus
      _config.subcards[0].setting.cache = res.cache
      _config.subcards[0].setting.align = res.align
      _config.subcards[0].setting.enable = res.enable
      _config.subcards[0].setting.verticalSpace = res.verticalSpace || ''
      _config.wrap.focus = res.focus
      _config.wrap.cache = res.cache
      _config.wrap.align = res.align
      _config.wrap.enable = res.enable
      _config.wrap.verticalSpace = res.verticalSpace || ''
      res.fields.forEach(item => {
        item.uuid = Utils.getuuid()
      })
      _config.subcards[0].fields = res.fields
      _config.subcards[0].subButton = res.subButton
      if (!res.prevButton) {
        res.prevButton = {label: '上一步', type: 'prev', enable: 'false', style: {marginRight: '15px', paddingTop: '5px', paddingBottom: '5px'}}
      }
      if (!res.nextButton) {
        res.nextButton = {label: '跳过', type: 'next', enable: 'false', style: {paddingTop: '5px', paddingBottom: '5px'}}
      }
      card.subcards.push(res)
      this.setState({
        group: res
      })
      this.updateComponent(card)
      notification.success({
        top: 92,
        message: '粘贴成功!',
        duration: 2
      confirm({
        content: `替换表单及按钮配置?`,
        onOk() {
          _this.updateComponent(_config)
        },
        onCancel() {}
      })
      return
    }
    let _config = fromJS(this.state.group).toJS()
    let fieldrepet = false // 字段重复
    _config.fields.forEach(item => {
    _config.subcards[0].fields.forEach(item => {
      if (res.field && item.field && item.field.toLowerCase() === res.field.toLowerCase()) {
        fieldrepet = true
      }
@@ -709,9 +604,9 @@
      })
      return
    }
    _config.fields.push(res)
    _config.subcards[0].fields.push(res)
    this.updateGroup(_config)
    this.updateComponent(_config)
    this.handleForm(res)
@@ -737,7 +632,28 @@
      }
    }
    _card.subcards[0].setting.focus = _card.wrap.focus
    _card.subcards[0].setting.cache = _card.wrap.cache
    _card.subcards[0].setting.align = _card.wrap.align
    _card.subcards[0].setting.enable = _card.wrap.enable
    _card.subcards[0].setting.verticalSpace = _card.wrap.verticalSpace
    this.updateComponent(_card)
  }
  clearGroup = () => {
    let card = fromJS(this.state.card).toJS()
    let _this = this
    card.subcards[0].fields = []
    confirm({
      content: `确定清空表单吗?`,
      onOk() {
        _this.updateComponent(card)
      },
      onCancel() {}
    })
  }
  clickComponent = (e) => {
@@ -748,17 +664,17 @@
  }
  render() {
    const { card, dict, group, appType } = this.state
    const { card, dict, appType } = this.state
    return (
      <div className="menu-normal-form-edit-box" style={resetStyle(card.style)} onClick={this.clickComponent} id={card.uuid}>
      <div className="menu-simple-form-edit-box" style={resetStyle(card.style)} onClick={this.clickComponent} id={card.uuid}>
        <NormalHeader config={card} updateComponent={this.updateComponent}/>
        <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={
          <div className="mk-popover-control">
            <PlusOutlined className="plus" title="添加分组" onClick={this.addCard}/>
            <NormalForm title="表单设置" width={800} update={this.updateWrap} getForms={this.getWrapForms}>
              <EditOutlined style={{color: '#1890ff'}} title="编辑"/>
            </NormalForm>
            <CopyComponent type="stepform" card={card}/>
            <CopyComponent type="simpleform" card={card}/>
            <PasteComponent config={card} options={['form', 'formgroup']} updateConfig={this.pasteForm} />
            <FontColorsOutlined className="style" title="调整样式" onClick={this.changeStyle}/>
            <UserComponent config={card}/>
@@ -769,17 +685,10 @@
        } trigger="hover">
          <ToolOutlined />
        </Popover>
        <FormTitle
          list={card.subcards}
          selectId={group ? group.uuid : ''}
          handleList={this.changecards}
          handleGroup={this.changeGroup}
          closeGroup={this.closeGroup}
          selectGroup={this.selectGroup}
        />
        {group ? <div className="form-area">
        <div className="form-area">
          <PlusOutlined className="plus" title="添加表单" onClick={this.addForm}/>
          <FieldsComponent config={group} type="form" plusFields={this.plusFields} />
          <FieldsComponent config={card.subcards[0]} type="form" plusFields={this.plusFields} />
          <span style={{color: 'red', marginLeft: '30px', cursor: 'pointer'}} onClick={this.clearGroup}>清空</span>
          <Switch checkedChildren={dict['model.switch.open']} unCheckedChildren={dict['model.switch.close']} defaultChecked={this.state.showField} onChange={(val) => this.setState({showField: val})} />
          {appType !== 'mob' ? <Button className="mk-cols-change" onClick={() => this.changecols(1)}>1列</Button> : null}
          {appType !== 'mob' ? <Button className="mk-cols-change" onClick={() => this.changecols(2)}>2列</Button> : null}
@@ -787,23 +696,23 @@
          {appType !== 'mob' ? <Button className="mk-cols-change" onClick={() => this.changecols(4)}>4列</Button> : null}
          <div style={{clear: 'both'}}></div>
          {appType !== 'mob' ? <CardComponent
            list={group.fields}
            setting={group.setting}
            list={card.subcards[0].fields}
            setting={card.subcards[0].setting}
            showField={this.state.showField}
            placeholder={dict['header.form.modal.placeholder']}
            handleList={this.handleList}
            handleForm={this.handleForm}
            closeForm={this.closeForm}
          /> : <MobCardComponent
            list={group.fields}
            setting={group.setting}
            list={card.subcards[0].fields}
            setting={card.subcards[0].setting}
            showField={this.state.showField}
            handleList={this.handleList}
            handleForm={this.handleForm}
            closeForm={this.closeForm}
          />}
          <FormAction config={card} group={group} updateconfig={this.updateGroup}/>
        </div> : null}
          <FormAction config={card} group={card.subcards[0]} updateconfig={this.updateGroup}/>
        </div>
        <div className="component-name">
          <div className="center">
            <div className="title">{card.name}</div>
@@ -842,4 +751,4 @@
  }
}
export default PropCardEditComponent
export default SimpleFormComponent
src/menu/components/form/simple-form/index.scss
New file
@@ -0,0 +1,88 @@
.menu-simple-form-edit-box {
  position: relative;
  box-sizing: border-box;
  background: #ffffff;
  background-position: center center;
  background-repeat: no-repeat;
  background-size: cover;
  min-height: 30px;
  .card-control {
    position: absolute;
    top: 0px;
    left: 0px;
    .anticon-tool {
      right: auto;
      left: 1px;
      padding: 1px;
    }
  }
  .anticon-tool {
    position: absolute;
    z-index: 2;
    font-size: 16px;
    right: 1px;
    top: 1px;
    cursor: pointer;
    padding: 5px;
    background: rgba(255, 255, 255, 0.55);
  }
  .page-card {
    position: relative;
    background: #ffffff;
    border-radius: 2px;
  }
  .form-area {
    position: relative;
    padding-top: 15px;
    .page-card {
      background: transparent;
    }
    >.plus {
      color: #26C281;
      cursor: pointer;
      padding: 4px 10px;
    }
    >button {
      float: right;
      margin-right: 10px;
    }
    >.mk-cols-change {
      height: 24px;
      padding: 0 10px;
    }
    >.quickly-add {
      display: inline-block;
      margin-left: 10px;
      button {
        color: #1890ff;
        background: transparent;
        border: none;
        box-shadow: none;
        padding: 0;
        height: 24px;
      }
    }
    .modal-fields-row {
      padding-top: 10px;
      padding-bottom: 30px;
    }
    .modal-fields-row:not(.mob-form) {
      padding-left: 10px;
      padding-right: 10px;
    }
    .am-list-item {
      background-color: transparent;
    }
  }
}
.menu-normal-form-edit-box::after {
  display: block;
  content: ' ';
  clear: both;
}
.menu-normal-form-edit-box:hover {
  z-index: 1;
  box-shadow: 0px 0px 4px #1890ff;
}
src/menu/components/form/simple-form/options.jsx
New file
@@ -0,0 +1,174 @@
import { fromJS } from 'immutable'
import MenuUtils from '@/utils/utils-custom.js'
/**
 * @description Wrap表单配置信息
 */
export default function (config) {
  let appType = sessionStorage.getItem('appType')
  let roleList = sessionStorage.getItem('sysRoles')
  let wrap = config.wrap
  if (roleList) {
    try {
      roleList = JSON.parse(roleList)
    } catch (e) {
      roleList = []
    }
  } else {
    roleList = []
  }
  let fields = [{field: '', label: '空'}]
  if (appType === 'mob') {
    config.subcards[0].fields.forEach(f => {
      if (f.field && ['select', 'text', 'number'].includes(f.type) && f.hidden !== 'true' && f.readonly !== 'true') {
        fields.push(f)
      }
    })
  } else {
    config.subcards[0].fields.forEach(f => {
      if (f.field && ['select', 'link', 'text', 'number'].includes(f.type) && f.hidden !== 'true' && f.readonly !== 'true') {
        fields.push(f)
      }
    })
  }
  let modules = []
  let menu = fromJS(window.GLOB.customMenu).toJS()
  modules = MenuUtils.getSupModules(menu.components, config.uuid) || []
  const wrapForm = [
    {
      type: 'text',
      field: 'title',
      label: '标题',
      initval: wrap.title || '',
      required: false
    },
    {
      type: 'text',
      field: 'name',
      label: '组件名称',
      initval: wrap.name || '',
      tooltip: '用于组件间的区分。',
      required: true
    },
    {
      type: 'number',
      field: 'width',
      label: '宽度',
      initval: wrap.width || 24,
      tooltip: '栅格布局,每行等分为24列。',
      min: 1,
      max: 24,
      precision: 0,
      required: true
    },
    {
      type: 'radio',
      field: 'datatype',
      label: '数据来源',
      initval: wrap.datatype || 'static',
      tooltip: '初始值来源于数据源或表单默认值。',
      required: false,
      options: [
        {value: 'dynamic', label: '动态'},
        {value: 'static', label: '静态'},
      ],
      controlFields: [
        {field: 'supModule', values: ['static']},
      ]
    },
    {
      type: 'select',
      field: 'focus',
      label: '焦点',
      initval: wrap.focus || '',
      required: false,
      options: fields
    },
    {
      type: 'radio',
      field: 'cache',
      label: '选项查询',
      initval: wrap.cache || 'true',
      tooltip: '需要通过数据源查询的选项,是否使用缓存。',
      required: false,
      options: [
        {value: 'true', label: '缓存'},
        {value: 'false', label: '实时'},
      ]
    },
    {
      type: 'radio',
      field: 'align',
      label: '表单排列',
      initval: wrap.align || 'left_right',
      required: false,
      options: [
        {value: 'left_right', label: '左右'},
        {value: 'up_down', label: '上下'},
      ],
      forbid: appType === 'mob'
    },
    {
      type: 'radio',
      field: 'verticalSpace',
      label: '竖向间隙',
      initval: wrap.verticalSpace || 'normal',
      tooltip: '正常间隙会预留出报错信息的位置,防止表单位置发生变化。',
      required: false,
      options: [
        {value: 'normal', label: '正常'},
        {value: 'middle', label: '中'},
        {value: 'small', label: '小'},
      ],
      forbid: appType === 'mob'
    },
    {
      type: 'radio',
      field: 'subEnable',
      label: '提交',
      initval: wrap.enable || 'true',
      required: false,
      options: [
        {value: 'true', label: '显示'},
        {value: 'false', label: '隐藏'},
      ]
    },
    {
      type: 'radio',
      field: 'permission',
      label: '权限验证',
      initval: wrap.permission || 'false',
      required: false,
      options: [
        {value: 'true', label: '启用'},
        {value: 'false', label: '禁用'},
      ],
      forbid: !appType
    },
    {
      type: 'cascader',
      field: 'supModule',
      label: '上级组件',
      initval: wrap.supModule || [],
      required: false,
      options: modules,
      allowClear: true
    },
    {
      type: 'multiselect',
      field: 'blacklist',
      label: '黑名单',
      initval: wrap.blacklist || [],
      required: false,
      options: roleList,
      forbid: !!appType
    },
  ]
  return wrapForm
}
src/menu/components/form/step-form/index.jsx
File was renamed from src/menu/components/form/normal-form/index.jsx
@@ -31,7 +31,7 @@
const { confirm } = Modal
class PropCardEditComponent extends Component {
class StepFormComponent extends Component {
  static propTpyes = {
    card: PropTypes.object,
    deletecomponent: PropTypes.func,
@@ -660,6 +660,9 @@
  }
  pasteForm = (res) => {
    if (res.subtype === 'simpleform') {
      res = res.subcards[0]
    }
    if (res.subButton) {
      let card = fromJS(this.state.card).toJS()
@@ -759,7 +762,7 @@
              <EditOutlined style={{color: '#1890ff'}} title="编辑"/>
            </NormalForm>
            <CopyComponent type="stepform" card={card}/>
            <PasteComponent config={card} options={['form', 'formgroup']} updateConfig={this.pasteForm} />
            <PasteComponent config={card} options={['form', 'formgroup', 'simpleform']} updateConfig={this.pasteForm} />
            <FontColorsOutlined className="style" title="调整样式" onClick={this.changeStyle}/>
            <UserComponent config={card}/>
            <DeleteOutlined className="close" title="删除组件" onClick={() => this.props.deletecomponent(card.uuid)} />
@@ -842,4 +845,4 @@
  }
}
export default PropCardEditComponent
export default StepFormComponent
src/menu/components/form/step-form/index.scss
src/menu/components/form/step-form/options.jsx
src/menu/components/form/tab-form/index.jsx
@@ -12,7 +12,7 @@
import { resetStyle } from '@/utils/utils-custom.js'
import MKEmitter from '@/utils/events.js'
import Utils from '@/utils/utils.js'
import getWrapForm from '../normal-form/options'
import getWrapForm from '../step-form/options'
import zhCN from '@/locales/zh-CN/model.js'
import enUS from '@/locales/en-US/model.js'
import './index.scss'
@@ -31,7 +31,7 @@
const { confirm } = Modal
class PropCardEditComponent extends Component {
class TabFormComponent extends Component {
  static propTpyes = {
    card: PropTypes.object,
    deletecomponent: PropTypes.func,
@@ -666,6 +666,9 @@
  }
  pasteForm = (res) => {
    if (res.subtype === 'simpleform') {
      res = res.subcards[0]
    }
    if (res.subButton) {
      let card = fromJS(this.state.card).toJS()
@@ -785,7 +788,7 @@
              <EditOutlined style={{color: '#1890ff'}} title="编辑"/>
            </NormalForm>
            <CopyComponent type="tabform" card={card}/>
            <PasteComponent config={card} options={['form', 'formgroup']} updateConfig={this.pasteForm} />
            <PasteComponent config={card} options={['form', 'formgroup', 'simpleform']} updateConfig={this.pasteForm} />
            <FontColorsOutlined className="style" title="调整样式" onClick={this.changeStyle}/>
            <UserComponent config={card}/>
            <DeleteOutlined className="close" title="删除组件" onClick={() => this.props.deletecomponent(card.uuid)} />
@@ -870,4 +873,4 @@
  }
}
export default PropCardEditComponent
export default TabFormComponent
src/menu/components/group/groupcomponents/card.jsx
@@ -14,7 +14,8 @@
const EditTable = asyncComponent(() => import('@/menu/components/table/edit-table'))
const BraftEditor = asyncComponent(() => import('@/menu/components/editor/braft-editor'))
const AntvScatter = asyncComponent(() => import('@/menu/components/chart/antv-scatter'))
const NormalForm = asyncComponent(() => import('@/menu/components/form/normal-form'))
const SimpleForm = asyncComponent(() => import('@/menu/components/form/simple-form'))
const StepForm = asyncComponent(() => import('@/menu/components/form/step-form'))
const TabForm = asyncComponent(() => import('@/menu/components/form/tab-form'))
const AntvDashboard = asyncComponent(() => import('@/menu/components/chart/antv-dashboard'))
const CarouselDataCard = asyncComponent(() => import('@/menu/components/carousel/data-card'))
@@ -68,8 +69,10 @@
      return (<NormalTree card={card} updateConfig={updateConfig} deletecomponent={delCard}/>)
    } else if (card.type === 'scatter') {
      return (<AntvScatter card={card} updateConfig={updateConfig} deletecomponent={delCard}/>)
    } else if (card.type === 'form' && card.subtype === 'simpleform') {
      return (<SimpleForm card={card} updateConfig={updateConfig} deletecomponent={delCard}/>)
    } else if (card.type === 'form' && card.subtype === 'stepform') {
      return (<NormalForm card={card} updateConfig={updateConfig} deletecomponent={delCard}/>)
      return (<StepForm card={card} updateConfig={updateConfig} deletecomponent={delCard}/>)
    } else if (card.type === 'form' && card.subtype === 'tabform') {
      return (<TabForm card={card} updateConfig={updateConfig} deletecomponent={delCard}/>)
    } else if (card.type === 'card' && card.subtype === 'datacard') {
src/menu/components/group/paste/index.jsx
@@ -24,7 +24,7 @@
  }
  pasteSubmit = () => {
    let options = ['datacard', 'propcard', 'balcony', 'timeline', 'stepform', 'tabform', 'normaltable', 'tablecard', 'line', 'bar', 'pie', 'dashboard', 'scatter', 'chart']
    let options = ['datacard', 'propcard', 'balcony', 'timeline', 'simpleform', 'stepform', 'tabform', 'normaltable', 'tablecard', 'line', 'bar', 'pie', 'dashboard', 'scatter', 'chart']
    let types = {
      login: '登录',
      navbar: '导航栏',
src/menu/components/share/normalheader/index.jsx
@@ -77,6 +77,11 @@
    }
    let _style = resetStyle(config.headerStyle)
    let _s = {display: 'block', flex: 1}
    if (show && ((config.wrap && config.wrap.searchable === 'true') || (hideSearch !== 'true' && config.search && config.search.length))) {
      _s = null
    }
    return (
      <div className={'normal-header' + (!show ? ' hidden' : '') + (config.wrap && config.wrap.searchable === 'true' ? ' tree-search' : '')} style={_style}>
        <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={
@@ -84,7 +89,7 @@
            <FontColorsOutlined className="style" title="调整样式" onClick={this.changeStyle}/>
          </div>
        } trigger="hover">
          <span className="title">{title}</span>
          <span className="title" style={_s}>{title}</span>
        </Popover>
        {config.wrap && config.wrap.searchable === 'true' ? <span className="ant-input-search ant-input-affix-wrapper"><span className="ant-input-suffix"><SearchOutlined /></span></span> : null}
        {hideSearch !== 'true' && config.search ? <SearchComponent config={config} updatesearch={this.props.updateComponent}/> : null}
src/menu/components/share/normalheader/index.scss
@@ -21,6 +21,9 @@
    flex: 1;
    padding-top: 5px;
  }
  .search-length0 {
    display: none;
  }
  .ant-input-search.ant-input-affix-wrapper {
    width: 50%;
    max-width: 150px;
src/menu/components/share/searchcomponent/index.jsx
@@ -289,7 +289,7 @@
    const { dict, searchlist, visible, sqlVerifing } = this.state
    return (
      <div className="model-custom-header-search-list">
      <div className={'model-custom-header-search-list search-length' + (searchlist.length)}>
        <DragElement
          list={searchlist}
          handleList={this.handleList}
src/menu/components/tabs/paste/index.jsx
@@ -71,7 +71,7 @@
  pasteSubmit = () => {
    const { Tab } = this.props
    let options = ['tabs', 'group', 'datacard', 'propcard', 'timeline', 'balcony', 'normaltable', 'mainsearch', 'stepform', 'tabform', 'tablecard', 'line', 'bar', 'pie', 'dashboard', 'scatter', 'chart']
    let options = ['tabs', 'group', 'datacard', 'propcard', 'timeline', 'balcony', 'normaltable', 'mainsearch', 'simpleform', 'stepform', 'tabform', 'tablecard', 'line', 'bar', 'pie', 'dashboard', 'scatter', 'chart']
    let types = {
      login: '登录',
      navbar: '导航栏',
src/menu/components/tabs/tabcomponents/card.jsx
@@ -17,7 +17,8 @@
const CarouselDataCard = asyncComponent(() => import('@/menu/components/carousel/data-card'))
const CarouselPropCard = asyncComponent(() => import('@/menu/components/carousel/prop-card'))
const TableCard = asyncComponent(() => import('@/menu/components/card/table-card'))
const NormalForm = asyncComponent(() => import('@/menu/components/form/normal-form'))
const SimpleForm = asyncComponent(() => import('@/menu/components/form/simple-form'))
const StepForm = asyncComponent(() => import('@/menu/components/form/step-form'))
const TabForm = asyncComponent(() => import('@/menu/components/form/tab-form'))
const NormalTable = asyncComponent(() => import('@/menu/components/table/normal-table'))
const EditTable = asyncComponent(() => import('@/menu/components/table/edit-table'))
@@ -73,8 +74,10 @@
      return (<NormalTree card={card} updateConfig={updateConfig} deletecomponent={delCard}/>)
    } else if (card.type === 'scatter') {
      return (<AntvScatter card={card} updateConfig={updateConfig} deletecomponent={delCard}/>)
    } else if (card.type === 'form' && card.subtype === 'simpleform') {
      return (<SimpleForm card={card} updateConfig={updateConfig} deletecomponent={delCard}/>)
    } else if (card.type === 'form' && card.subtype === 'stepform') {
      return (<NormalForm card={card} updateConfig={updateConfig} deletecomponent={delCard}/>)
      return (<StepForm card={card} updateConfig={updateConfig} deletecomponent={delCard}/>)
    } else if (card.type === 'form' && card.subtype === 'tabform') {
      return (<TabForm card={card} updateConfig={updateConfig} deletecomponent={delCard}/>)
    } else if (card.type === 'tabs') {
src/menu/menushell/card.jsx
@@ -19,7 +19,8 @@
const TableCard = asyncComponent(() => import('@/menu/components/card/table-card'))
const NormalTable = asyncComponent(() => import('@/menu/components/table/normal-table'))
const EditTable = asyncComponent(() => import('@/menu/components/table/edit-table'))
const NormalForm = asyncComponent(() => import('@/menu/components/form/normal-form'))
const SimpleForm = asyncComponent(() => import('@/menu/components/form/simple-form'))
const StepForm = asyncComponent(() => import('@/menu/components/form/step-form'))
const TabForm = asyncComponent(() => import('@/menu/components/form/tab-form'))
const NormalGroup = asyncComponent(() => import('@/menu/components/group/normal-group'))
const BraftEditor = asyncComponent(() => import('@/menu/components/editor/braft-editor'))
@@ -78,8 +79,10 @@
      return (<NormalTree card={card} updateConfig={updateConfig} deletecomponent={delCard}/>)
    } else if (card.type === 'scatter') {
      return (<AntvScatter card={card} updateConfig={updateConfig} deletecomponent={delCard}/>)
    } else if (card.type === 'form' && card.subtype === 'simpleform') {
      return (<SimpleForm card={card} updateConfig={updateConfig} deletecomponent={delCard}/>)
    } else if (card.type === 'form' && card.subtype === 'stepform') {
      return (<NormalForm card={card} updateConfig={updateConfig} deletecomponent={delCard}/>)
      return (<StepForm card={card} updateConfig={updateConfig} deletecomponent={delCard}/>)
    } else if (card.type === 'form' && card.subtype === 'tabform') {
      return (<TabForm card={card} updateConfig={updateConfig} deletecomponent={delCard}/>)
    } else if (card.type === 'tabs') {
src/menu/modulesource/option.jsx
@@ -18,6 +18,7 @@
import Carousel from '@/assets/mobimg/carousel.png'
import Carousel1 from '@/assets/mobimg/carousel1.png'
import form from '@/assets/mobimg/form.png'
import simpleform from '@/assets/mobimg/simple-form.png'
import tabForm from '@/assets/mobimg/tab-form.png'
import dashboard from '@/assets/mobimg/dashboard.png'
import ratioboard from '@/assets/mobimg/ratioboard.png'
@@ -34,6 +35,7 @@
  { 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: simpleform, component: 'form', subtype: 'simpleform', title: '表单', width: 24, forbid: ['billPrint'] },
  { type: 'menu', url: form, component: 'form', subtype: 'stepform', title: '表单(分步)', width: 24, forbid: ['billPrint'] },
  { type: 'menu', url: tabForm, component: 'form', subtype: 'tabform', title: '表单(tab页)', width: 24, forbid: ['billPrint'] },
  { type: 'menu', url: Carousel, component: 'carousel', subtype: 'datacard', title: '轮播-动态数据', width: 24, forbid: ['billPrint'] },
src/menu/pastecontroller/index.jsx
@@ -66,7 +66,7 @@
  }
  pasteSubmit = () => {
    let options = ['tabs', 'menubar', 'topbar', 'timeline', 'datacard', 'propcard', 'mainsearch', 'stepform', 'tabform', 'balcony', 'group', 'normaltable', 'tablecard', 'line', 'bar', 'pie', 'dashboard', 'scatter']
    let options = ['tabs', 'menubar', 'topbar', 'timeline', 'datacard', 'propcard', 'mainsearch', 'simpleform', 'stepform', 'tabform', 'balcony', 'group', 'normaltable', 'tablecard', 'line', 'bar', 'pie', 'dashboard', 'scatter']
    this.pasteFormRef.handleConfirm().then(res => {
      if ((res.copyType === 'menubar' || res.copyType === 'topbar') && sessionStorage.getItem('appType') !== 'mob') {
src/mob/components/tabs/tabcomponents/card.jsx
@@ -16,7 +16,8 @@
const CarouselDataCard = asyncComponent(() => import('@/menu/components/carousel/data-card'))
const CarouselPropCard = asyncComponent(() => import('@/menu/components/carousel/prop-card'))
const TableCard = asyncComponent(() => import('@/menu/components/card/table-card'))
const NormalForm = asyncComponent(() => import('@/menu/components/form/normal-form'))
const SimpleForm = asyncComponent(() => import('@/menu/components/form/simple-form'))
const StepForm = asyncComponent(() => import('@/menu/components/form/step-form'))
const TabForm = asyncComponent(() => import('@/menu/components/form/tab-form'))
const NormalTable = asyncComponent(() => import('@/menu/components/table/normal-table'))
const NormalGroup = asyncComponent(() => import('@/menu/components/group/normal-group'))
@@ -72,8 +73,10 @@
      return (<NormalTree card={card} updateConfig={updateConfig} deletecomponent={delCard}/>)
    } else if (card.type === 'scatter') {
      return (<AntvScatter card={card} updateConfig={updateConfig} deletecomponent={delCard}/>)
    } else if (card.type === 'form' && card.subtype === 'simpleform') {
      return (<SimpleForm card={card} updateConfig={updateConfig} deletecomponent={delCard}/>)
    } else if (card.type === 'form' && card.subtype === 'stepform') {
      return (<NormalForm card={card} updateConfig={updateConfig} deletecomponent={delCard}/>)
      return (<StepForm card={card} updateConfig={updateConfig} deletecomponent={delCard}/>)
    } else if (card.type === 'form' && card.subtype === 'tabform') {
      return (<TabForm card={card} updateConfig={updateConfig} deletecomponent={delCard}/>)
    } else if (card.type === 'tabs') {
src/mob/mobshell/card.jsx
@@ -16,7 +16,8 @@
const CarouselPropCard = asyncComponent(() => import('@/menu/components/carousel/prop-card'))
const TableCard = asyncComponent(() => import('@/menu/components/card/table-card'))
const NormalTable = asyncComponent(() => import('@/menu/components/table/normal-table'))
const NormalForm = asyncComponent(() => import('@/menu/components/form/normal-form'))
const SimpleForm = asyncComponent(() => import('@/menu/components/form/simple-form'))
const StepForm = asyncComponent(() => import('@/menu/components/form/step-form'))
const TabForm = asyncComponent(() => import('@/menu/components/form/tab-form'))
const NormalGroup = asyncComponent(() => import('@/menu/components/group/normal-group'))
const CodeSandbox = asyncComponent(() => import('@/menu/components/code/sandbox'))
@@ -91,8 +92,10 @@
      return (<AntvDashboard card={card} updateConfig={updateConfig} deletecomponent={delCard}/>)
    } else if (card.type === 'scatter') {
      return (<AntvScatter card={card} updateConfig={updateConfig} deletecomponent={delCard}/>)
    } else if (card.type === 'form' && card.subtype === 'simpleform') {
      return (<SimpleForm card={card} updateConfig={updateConfig} deletecomponent={delCard}/>)
    } else if (card.type === 'form' && card.subtype === 'stepform') {
      return (<NormalForm card={card} updateConfig={updateConfig} deletecomponent={delCard}/>)
      return (<StepForm card={card} updateConfig={updateConfig} deletecomponent={delCard}/>)
    } else if (card.type === 'form' && card.subtype === 'tabform') {
      return (<TabForm card={card} updateConfig={updateConfig} deletecomponent={delCard}/>)
    } else if (card.type === 'tabs') {
src/mob/modulesource/option.jsx
@@ -38,6 +38,7 @@
  { 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: 'simpleform', title: '表单', width: 24 },
  { type: 'menu', url: form, component: 'form', subtype: 'stepform', title: '表单(分步)', width: 24 },
  { type: 'menu', url: tabForm, component: 'form', subtype: 'tabform', title: '表单(tab页)', width: 24 },
  { type: 'menu', url: Carousel, component: 'carousel', subtype: 'datacard', title: '轮播-动态数据', width: 24 },
src/pc/menushell/card.jsx
@@ -17,7 +17,8 @@
const NormalTable = asyncComponent(() => import('@/menu/components/table/normal-table'))
const EditTable = asyncComponent(() => import('@/menu/components/table/edit-table'))
const NormalGroup = asyncComponent(() => import('@/menu/components/group/normal-group'))
const NormalForm = asyncComponent(() => import('@/menu/components/form/normal-form'))
const SimpleForm = asyncComponent(() => import('@/menu/components/form/simple-form'))
const StepForm = asyncComponent(() => import('@/menu/components/form/step-form'))
const TabForm = asyncComponent(() => import('@/menu/components/form/tab-form'))
const BraftEditor = asyncComponent(() => import('@/menu/components/editor/braft-editor'))
const CodeSandbox = asyncComponent(() => import('@/menu/components/code/sandbox'))
@@ -84,8 +85,10 @@
      return (<AntvBar card={card} updateConfig={updateConfig} deletecomponent={delCard}/>)
    } else if (card.type === 'navbar') {
      return (<NormalNavbar card={card} updateConfig={updateConfig} deletecomponent={delCard}/>)
    } else if (card.type === 'form' && card.subtype === 'simpleform') {
      return (<SimpleForm card={card} updateConfig={updateConfig} deletecomponent={delCard}/>)
    } else if (card.type === 'form' && card.subtype === 'stepform') {
      return (<NormalForm card={card} updateConfig={updateConfig} deletecomponent={delCard}/>)
      return (<StepForm card={card} updateConfig={updateConfig} deletecomponent={delCard}/>)
    } else if (card.type === 'form' && card.subtype === 'tabform') {
      return (<TabForm card={card} updateConfig={updateConfig} deletecomponent={delCard}/>)
    } else if (card.type === 'search') {
src/tabviews/custom/components/form/simple-form/index.jsx
copy from src/tabviews/custom/components/form/normal-form/index.jsx copy to src/tabviews/custom/components/form/simple-form/index.jsx
File was copied from src/tabviews/custom/components/form/normal-form/index.jsx
@@ -2,7 +2,7 @@
import PropTypes from 'prop-types'
import { is, fromJS } from 'immutable'
import { connect } from 'react-redux'
import { Spin, notification, Button } from 'antd'
import { Spin, notification } from 'antd'
import Api from '@/api'
import UtilsDM from '@/utils/utils-datamanage.js'
@@ -15,8 +15,9 @@
const MutilForm = asyncSpinComponent(() => import('@/tabviews/zshare/mutilform'))
const NormalButton = asyncComponent(() => import('@/tabviews/zshare/actionList/normalbutton'))
const NormalHeader = asyncComponent(() => import('@/tabviews/custom/components/share/normalheader'))
class NormalForm extends Component {
class SimpleForm extends Component {
  static propTpyes = {
    BID: PropTypes.any,              // 父级Id
    data: PropTypes.array,           // 统一查询数据
@@ -58,54 +59,23 @@
      _data = {$$empty: true}
    }
    if (!config.wrap.groupLabel) {
      if (config.subcards.length > 1) {
        config.wrap.groupLabel = 'show'
      } else {
        config.wrap.groupLabel = 'hidden'
      }
    }
    config.subcards = config.subcards.map((group, i) => {
      group.sort = i + 1
      if (i === 0) {
        group.prevButton.enable = 'false'
      }
      if (i + 1 === config.subcards.length) {
        group.nextButton.enable = 'false'
      }
      if (group.subButton.enable === 'false') {
        group.subButton.style.display = 'none'
      }
      if (group.prevButton.enable === 'false' && group.subButton.enable === 'false' && group.nextButton.enable === 'false') {
        group.$button = 'no-button'
      }
      return group
    })
    let _group = config.subcards[0]
    if (_data && config.wrap.statusControl && _data[config.wrap.statusControl]) {
      let _status = _data[config.wrap.statusControl]
      let _groups = config.subcards.filter(item => item.setting.status === _status)[0]
      _group = _groups || _group
    if (_group.subButton.enable === 'false') {
      _group.subButton.style.display = 'none'
      _group.$button = 'no-button'
    }
    this.setState({
      sync: _sync,
      data: _data,
      group: _group,
      step: _group.sort - 1,
      BID: BID || '',
      BData: BData || '',
      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') {
      if (config.wrap.datatype !== 'static' && config.setting.sync !== 'true' && config.setting.onload === 'true') {
        setTimeout(() => {
          this.loadData()
        }, config.setting.delay || 0)
@@ -138,11 +108,10 @@
   * @description 图表数据更新,刷新内容
   */
  UNSAFE_componentWillReceiveProps (nextProps) {
    const { sync, config, group } = this.state
    const { sync, config } = this.state
    if (sync && !is(fromJS(this.props.data), fromJS(nextProps.data))) {
      let _data = {$$empty: true}
      let _group = group
      if (nextProps.data && nextProps.data[config.dataName]) {
        _data = nextProps.data[config.dataName]
        if (Array.isArray(_data)) {
@@ -150,13 +119,7 @@
        }
      }
      if (config.wrap.statusControl && _data[config.wrap.statusControl]) {
        let _status = _data[config.wrap.statusControl]
        let _groups = config.subcards.filter(item => item.setting.status === _status)[0]
        _group = _groups || _group
      }
      this.setState({sync: false, data: _data, group: _group, step: _group.sort - 1,})
      this.setState({sync: false, data: _data})
    } else if (config.setting.syncRefresh && nextProps.mainSearch && !is(fromJS(this.props.mainSearch), fromJS(nextProps.mainSearch))) {
      this.setState({}, () => {
        this.loadData()
@@ -221,18 +184,6 @@
  }
  execSuccess = (btn, id) => {
    const { config, group } = this.state
    if (config.subcards.length > group.sort) {
      let _group = config.subcards.filter(item => item.sort === (group.sort + 1))[0]
      this.setState({group: null, step: group.sort}, () => {
        this.setState({group: _group})
      })
    } else {
      this.setState({step: group.sort})
    }
    if (btn.linkmenu && btn.linkmenu.length > 0) {
      let menu_id = btn.linkmenu[btn.linkmenu.length - 1]
      let menu = this.props.permMenus.filter(m => m.MenuID === menu_id)[0] || ''
@@ -282,31 +233,12 @@
    let result = await Api.genericInterface(param)
    if (result.status) {
      let _data = result.data && result.data[0] ? result.data[0] : {$$empty: true}
      let _group = this.state.group
      if (type === 'refresh') {
        _group = config.subcards[0]
      }
      if (config.wrap.statusControl && _data[config.wrap.statusControl]) {
        let _status = _data[config.wrap.statusControl]
        let _groups = config.subcards.filter(item => item.setting.status === _status)[0]
        _group = _groups || _group
      }
      let step = this.state.step
      if (config.subcards.length !== _group.sort || config.subcards.length !== step) {
        step = _group.sort - 1
      }
      this.setState({
        group: null,
        step: step,
        data: _data,
        data: null,
        loading: false
      }, () => {
        this.setState({group: _group})
        this.setState({data: _data})
      })
    } else {
      this.setState({
@@ -330,48 +262,19 @@
    })
  }
  prevStep = () => {
    const { config, group } = this.state
    let _group = config.subcards.filter(item => item.sort === (group.sort - 1))[0]
    this.setState({group: null, step: group.sort - 2}, () => {
      this.setState({group: _group})
    })
  }
  nextStep = () => {
    const { config, group } = this.state
    let _group = config.subcards.filter(item => item.sort === (group.sort + 1))[0]
    this.setState({group: null, step: group.sort}, () => {
      this.setState({group: _group})
    })
  }
  render() {
    const { config, loading, BID, BData, data, group, dict, step } = this.state
    const { config, loading, BID, BData, data, group, dict } = this.state
    return (
      <div className="custom-normal-form-box" id={'anchor' + config.uuid} style={{...config.style}}>
      <div className="custom-simple-form-box" id={'anchor' + config.uuid} style={{...config.style}}>
        {loading ?
          <div className="loading-mask">
            <div className="ant-spin-blur"></div>
            <Spin />
          </div> : null
        }
        {config.wrap.groupLabel !== 'hidden' ? <div className="mk-normal-form-title">
          {config.subcards.map(card => (
            <div key={card.uuid} className={'form-title' + (card.sort <= step ? ' active' : '')}>
              <span className="form-sort" style={{background: config.wrap.color}}>{card.sort}</span>
              <span className="before-line" style={{background: config.wrap.color}}></span>
              <span className="after-line" style={{background: config.wrap.color}}></span>
              {card.setting.title}
            </div>))
          }
        </div> : null}
        {group && data ? <MutilForm
        <NormalHeader config={config} />
        {data ? <MutilForm
          BID={BID}
          BData={BData}
          dict={dict}
@@ -380,8 +283,7 @@
          inputSubmit={() => this.mkFormSubmit(group.uuid)}
          wrappedComponentRef={(inst) => this.formRef = inst}
        /> : null}
        {group && data ? <div className={'mk-form-action ' + (group.$button || '')}>
          {group.prevButton.enable === 'true' ? <Button type="link" className="prev" onClick={this.prevStep} style={group.prevButton.style}>{group.prevButton.label}</Button> : null}
        {data ? <div className={'mk-form-action ' + (group.$button || '')}>
          <NormalButton
            BID={BID}
            btn={group.subButton}
@@ -389,7 +291,6 @@
            columns={config.columns}
            selectedData={data.$$empty ? [] : [data]}
          />
          {group.nextButton.enable === 'true' ? <Button type="link" className="skip" onClick={this.nextStep} style={group.nextButton.style}>{group.nextButton.label}</Button> : null}
        </div> : null}
      </div>
    )
@@ -406,4 +307,4 @@
  return {}
}
export default connect(mapStateToProps, mapDispatchToProps)(NormalForm)
export default connect(mapStateToProps, mapDispatchToProps)(SimpleForm)
src/tabviews/custom/components/form/simple-form/index.scss
New file
@@ -0,0 +1,53 @@
.custom-simple-form-box {
  background: #ffffff;
  background-position: center center;
  background-repeat: no-repeat;
  background-size: cover;
  position: relative;
  min-height: 50px;
  .main-form-field {
    padding-top: 20px;
  }
  .mk-form-action {
    position: relative;
    text-align: center;
    padding-bottom: 10px;
    .submit {
      min-width: 70px;
      border: none;
    }
  }
  .mk-form-action.no-button {
    padding: 0;
    height: 0;
  }
  .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-simple-form-box::after {
  content: ' ';
  display: block;
  clear: both;
}
src/tabviews/custom/components/form/step-form/index.jsx
File was renamed from src/tabviews/custom/components/form/normal-form/index.jsx
@@ -16,7 +16,7 @@
const MutilForm = asyncSpinComponent(() => import('@/tabviews/zshare/mutilform'))
const NormalButton = asyncComponent(() => import('@/tabviews/zshare/actionList/normalbutton'))
class NormalForm extends Component {
class StepForm extends Component {
  static propTpyes = {
    BID: PropTypes.any,              // 父级Id
    data: PropTypes.array,           // 统一查询数据
@@ -406,4 +406,4 @@
  return {}
}
export default connect(mapStateToProps, mapDispatchToProps)(NormalForm)
export default connect(mapStateToProps, mapDispatchToProps)(StepForm)
src/tabviews/custom/components/form/step-form/index.scss
src/tabviews/custom/components/group/normal-group/index.jsx
@@ -25,7 +25,7 @@
const PropCard = asyncComponent(() => import('@/tabviews/custom/components/card/prop-card'))
const BraftEditor = asyncComponent(() => import('@/tabviews/custom/components/editor/braft-editor'))
const SandBox = asyncComponent(() => import('@/tabviews/custom/components/code/sand-box'))
const NormalForm = asyncComponent(() => import('@/tabviews/custom/components/form/normal-form'))
const NormalForm = asyncComponent(() => import('@/tabviews/custom/components/form/step-form'))
const TabForm = asyncComponent(() => import('@/tabviews/custom/components/form/tab-form'))
const NormalTree = asyncComponent(() => import('@/tabviews/custom/components/tree/antd-tree'))
const CarouselDataCard = asyncComponent(() => import('@/tabviews/custom/components/carousel/data-card'))
src/tabviews/custom/components/share/normalheader/index.scss
@@ -41,6 +41,12 @@
    }
  }
}
.normal-header:not(.header-search) {
  .title {
    display: block;
    float: none;
  }
}
.header-search.normal-header {
  display: flex;
}
src/tabviews/custom/components/share/tabtransfer/index.jsx
@@ -28,7 +28,8 @@
const NormalGroup = asyncComponent(() => import('@/tabviews/custom/components/group/normal-group'))
const BraftEditor = asyncComponent(() => import('@/tabviews/custom/components/editor/braft-editor'))
const SandBox = asyncComponent(() => import('@/tabviews/custom/components/code/sand-box'))
const NormalForm = asyncComponent(() => import('@/tabviews/custom/components/form/normal-form'))
const SimpleForm = asyncComponent(() => import('@/tabviews/custom/components/form/simple-form'))
const StepForm = asyncComponent(() => import('@/tabviews/custom/components/form/step-form'))
const TabForm = asyncComponent(() => import('@/tabviews/custom/components/form/tab-form'))
const NormalTree = asyncComponent(() => import('@/tabviews/custom/components/tree/antd-tree'))
const CarouselDataCard = asyncComponent(() => import('@/tabviews/custom/components/carousel/data-card'))
@@ -252,10 +253,16 @@
            <NormalGroup config={item} BID={BID} bids={bids} mainSearch={mainSearch} menuType={menuType} />
          </Col>
        )
      } else if (item.type === 'form' && item.subtype === 'simpleform') {
        return (
          <Col span={item.width} key={item.uuid}>
            <SimpleForm config={item} data={data} BID={BID} BData={BData} mainSearch={mainSearch} menuType={menuType} />
          </Col>
        )
      } else if (item.type === 'form' && item.subtype === 'stepform') {
        return (
          <Col span={item.width} key={item.uuid}>
            <NormalForm config={item} data={data} BID={BID} BData={BData} mainSearch={mainSearch} menuType={menuType} />
            <StepForm config={item} data={data} BID={BID} BData={BData} mainSearch={mainSearch} menuType={menuType} />
          </Col>
        )
      } else if (item.type === 'form' && item.subtype === 'tabform') {
src/tabviews/custom/components/tree/antd-tree/index.jsx
@@ -470,7 +470,7 @@
          </div> : null
        }
        {config.wrap.title || config.wrap.searchable === 'true' ? <div className="tree-header" style={config.headerStyle}>
          <span className="title">{config.wrap.title}</span>
          <span className={'title ' + (config.wrap.searchable !== 'true' ? 'search-unable' : '')}>{config.wrap.title}</span>
          {config.wrap.searchable === 'true' ? <Search allowClear onSearch={this.treeFilter} /> : null}
        </div> : null}
        {treeNodes && treeNodes.length > 0 ? <div className="tree-box" style={{height: config.wrap.contentHeight}}>
src/tabviews/custom/components/tree/antd-tree/index.scss
@@ -24,6 +24,10 @@
      position: relative;
      z-index: 1;
    }
    .title.search-unable {
      display: block;
      float: none;
    }
    .ant-input-search.ant-input-affix-wrapper {
      width: 50%;
      max-width: 150px;
src/tabviews/custom/index.jsx
@@ -23,7 +23,8 @@
const AntvScatter = asyncComponent(() => import('./components/chart/antv-scatter'))
const DataCard = asyncComponent(() => import('./components/card/data-card'))
const PropCard = asyncComponent(() => import('./components/card/prop-card'))
const NormalForm = asyncComponent(() => import('./components/form/normal-form'))
const SimpleForm = asyncComponent(() => import('./components/form/simple-form'))
const StepForm = asyncComponent(() => import('./components/form/step-form'))
const TabForm = asyncComponent(() => import('./components/form/tab-form'))
const CarouselDataCard = asyncComponent(() => import('./components/carousel/data-card'))
const CarouselPropCard = asyncComponent(() => import('./components/carousel/prop-card'))
@@ -1192,10 +1193,16 @@
            <AntvDashboard config={item} data={data} BID={_bid} mainSearch={mainSearch} menuType={menuType} />
          </Col>
        )
      } else if (item.type === 'form' && item.subtype === 'simpleform') {
        return (
          <Col span={item.width} key={item.uuid}>
            <SimpleForm config={item} data={data} BID={_bid} mainSearch={mainSearch} menuType={menuType} />
          </Col>
        )
      } else if (item.type === 'form' && item.subtype === 'stepform') {
        return (
          <Col span={item.width} key={item.uuid}>
            <NormalForm config={item} data={data} BID={_bid} mainSearch={mainSearch} menuType={menuType} />
            <StepForm config={item} data={data} BID={_bid} mainSearch={mainSearch} menuType={menuType} />
          </Col>
        )
      } else if (item.type === 'form' && item.subtype === 'tabform') {
src/views/mobdesign/index.jsx
@@ -1010,12 +1010,14 @@
            }
          })
        } else if (item.type === 'form') {
          m.children = item.subcards.map(m => {
            return {
              key: m.uuid,
              title: m.setting.title
            }
          })
          if (item.subtype !== 'simpleform') {
            m.children = item.subcards.map(m => {
              return {
                key: m.uuid,
                title: m.setting.title
              }
            })
          }
        } else if (item.type === 'table' && item.subtype === 'normaltable') {
          item.action && item.action.forEach(btn => {
            if (btn.hidden === 'true') return
src/views/pcdesign/index.jsx
@@ -1011,12 +1011,14 @@
            }
          })
        } else if (item.type === 'form') {
          m.children = item.subcards.map(m => {
            return {
              key: m.uuid,
              title: m.setting.title
            }
          })
          if (item.subtype !== 'simpleform') {
            m.children = item.subcards.map(m => {
              return {
                key: m.uuid,
                title: m.setting.title
              }
            })
          }
        } else if (item.type === 'table' && (item.subtype === 'normaltable' || item.subtype === 'editable')) {
          item.action && item.action.forEach(btn => {
            if (btn.hidden === 'true') return