king
2020-10-20 7b01bec1609710729a868093ad69484ebea82d80
2020-10-20
26个文件已修改
8个文件已添加
1642 ■■■■ 已修改文件
src/menu/actioncomponent/formconfig.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/card/cardcellcomponent/dragaction/index.jsx 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/card/cardcellcomponent/formconfig.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/card/cardcellcomponent/index.jsx 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/card/cardcomponent/settingform/index.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/card/data-card/wrapsetting/settingform/index.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/chart/antv-bar/chartcompile/formconfig.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/tabs/tabsetting/settingform/index.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/mob/colorsketch/index.jsx 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/calendar/index.jsx 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/card/data-card/index.jsx 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/index.jsx 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/treepage/index.jsx 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/checkCard/index.jsx 56 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/checkCard/index.scss 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/fileupload/index.jsx 22 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/modalconfig/checkCard/index.jsx 74 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/modalconfig/checkCard/index.scss 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/modalconfig/dragelement/card.jsx 26 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/modalconfig/dragelement/index.jsx 69 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/modalconfig/index.jsx 112 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/modalconfig/index.scss 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/modalconfig/source.jsx 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/treesettingcomponent/settingform/datasource/index.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/zshare/createinterface/index.jsx 11 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/zshare/formconfig.jsx 146 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/zshare/modalform/datatable/index.jsx 368 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/zshare/modalform/datatable/index.scss 57 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/zshare/modalform/fieldtable/index.jsx 308 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/zshare/modalform/fieldtable/index.scss 52 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/zshare/modalform/index.jsx 194 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/zshare/modalform/index.scss 24 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/zshare/modalform/modaleditable/index.jsx 26 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/zshare/modalform/modaleditable/index.scss 7 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/actioncomponent/formconfig.jsx
@@ -299,7 +299,7 @@
      precision: 0,
      label: '宽度',
      initVal: card.width || 12,
      tooltip: '每行等分为24份。',
      tooltip: '栅格布局,每行等分为24列。',
      forbid: type !== 'card',
      required: true
    },
src/menu/components/card/cardcellcomponent/dragaction/index.jsx
@@ -44,7 +44,6 @@
  const doubleClickCard = id => {
    const { card } = findCard(id)
    console.log(card)
    if (card.OpenType === 'pop') {
      handleSubConfig(card)
    }
src/menu/components/card/cardcellcomponent/formconfig.jsx
@@ -171,7 +171,7 @@
      precision: 0,
      label: '宽度',
      initVal: card.width || 12,
      tooltip: '每行等分为24份。',
      tooltip: '栅格布局,每行等分为24列。',
      required: true
    },
    {
src/menu/components/card/cardcellcomponent/index.jsx
@@ -463,7 +463,6 @@
    const { elements } = this.state
    
    this.verifyRef.handleConfirm().then(res => {
      console.log(res)
      let _elements = elements.map(cell => {
        if (cell.uuid === res.uuid) {
          res.eleType = 'button'
@@ -484,7 +483,7 @@
  }
  handleSubConfig = (item) => {
    console.log(item)
  }
  render() {
src/menu/components/card/cardcomponent/settingform/index.jsx
@@ -44,7 +44,7 @@
          <Row gutter={24}>
            <Col span={12}>
              <Form.Item label={
                <Tooltip placement="topLeft" title="栅格布局,每行等分24份。">
                <Tooltip placement="topLeft" title="栅格布局,每行等分为24列。">
                  <Icon type="question-circle" />
                  卡片宽度
                </Tooltip>
src/menu/components/card/data-card/wrapsetting/settingform/index.jsx
@@ -62,7 +62,7 @@
            </Col>
            <Col span={12}>
              <Form.Item label={
                <Tooltip placement="topLeft" title="栅格布局,每行等分24份。">
                <Tooltip placement="topLeft" title="栅格布局,每行等分为24列。">
                  <Icon type="question-circle" />
                  宽度
                </Tooltip>
src/menu/components/chart/antv-bar/chartcompile/formconfig.jsx
@@ -57,7 +57,7 @@
      key: 'width',
      label: '宽度',
      initVal: card.width,
      tooltip: '栅格布局,每行等分24份。',
      tooltip: '栅格布局,每行等分为24列。',
      min: 1,
      max: 24,
      decimal: 0,
src/menu/components/tabs/tabsetting/settingform/index.jsx
@@ -69,7 +69,7 @@
            </Col>
            <Col span={12}>
              <Form.Item label={
                <Tooltip placement="topLeft" title="栅格布局,每行等分24份。">
                <Tooltip placement="topLeft" title="栅格布局,每行等分为24列。">
                  <Icon type="question-circle" />
                  宽度
                </Tooltip>
src/mob/colorsketch/index.jsx
@@ -19,7 +19,22 @@
    onChange: PropTypes.func
  }
  state = {
    color: this.props.defaultValue || this.props.value,
    color: '',
  }
  UNSAFE_componentWillMount () {
    const { defaultValue, value } = this.props
    let initVal = ''
    if (this.props['data-__meta']) {
      initVal = this.props['data-__meta'].initialValue
    } else if (defaultValue) {
      initVal = defaultValue
    } else if (value) {
      initVal = value
    }
    this.setState({color: initVal})
  }
  handleChange = (color) => {
src/tabviews/calendar/index.jsx
@@ -562,6 +562,7 @@
  }
  render() {
    const { menuType } = this.props
    const { BID, searchlist, loadingview, viewlost, config, loading, data, triggerTime } = this.state
    return (
@@ -572,13 +573,13 @@
            BID={BID}
            dict={this.state.dict}
            searchlist={searchlist}
            menuType={this.props.menuType}
            menuType={menuType}
            dataManager={this.props.dataManager}
            refreshdata={this.refreshbysearch}
          /> : null
        }
        {config && config.calendar ? <CalendarComponent calendar={config.calendar} loading={loading} data={data} triggerDate={this.triggerDate} changeDate={this.changeDate}/> : null}
        {options.sysType !== 'cloud' ? <Button
        {options.sysType !== 'cloud' && menuType !== 'HS' ? <Button
          icon="copy"
          shape="circle"
          className="common-table-copy"
src/tabviews/custom/components/card/data-card/index.jsx
@@ -37,7 +37,6 @@
  UNSAFE_componentWillMount () {
    let _config = fromJS(this.props.config).toJS()
    console.log(_config)
    this.setState({
      config: _config,
src/tabviews/custom/index.jsx
@@ -469,13 +469,14 @@
  render() {
    const { menuType } = this.props
    const { loadingview, viewlost, config } = this.state
    return (
      <div className="custom-page-wrap" id={this.state.ContainerId} style={config ? config.style : null}>
        {loadingview && <Spin size="large" />}
        <Row>{this.getComponents()}</Row>
        {options.sysType !== 'cloud' ? <Button
        {options.sysType !== 'cloud' && menuType !== 'HS' ? <Button
          icon="copy"
          shape="circle"
          className="common-table-copy"
src/tabviews/treepage/index.jsx
@@ -754,6 +754,7 @@
  }
  render() {
    const { menuType } = this.props
    const { setting, loadingview, viewlost, config, triggerBtn, userConfig, tabActive, tabgroups, treeNodes, treedata, expandedKeys, selectedKeys } = this.state
    return (
@@ -822,8 +823,7 @@
            )}
          </Col>
        </Row> : null}
        {options.sysType !== 'cloud' ? <Button
        {options.sysType !== 'cloud' && menuType !== 'HS' ? <Button
          icon="copy"
          shape="circle"
          className="tree-page-copy"
src/tabviews/zshare/checkCard/index.jsx
New file
@@ -0,0 +1,56 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
// import { fromJS } from 'immutable'
import { Col, Row } from 'antd'
import './index.scss'
class CheckCard extends Component {
  static propTpyes = {
    multiple: PropTypes.bool,    // 是否可多选
    width: PropTypes.number,     // 宽度
    display: PropTypes.string,   // 显示为:text(文本)、picture(图片)
    fields: PropTypes.array,     // 字段集
    options: PropTypes.array,    // 数据列表
    onChange: PropTypes.func,    // 数据切换
  }
  state = {
    selectKeys: null,       // 选中数据id
  }
  UNSAFE_componentWillMount () {
  }
  UNSAFE_componentWillReceiveProps (nextProps) {
  }
  getCards = () => {
    const { display, options, fields } = this.props
    if (display === 'picture') {
      return options.map(item => {
        <Col>
          <div>
            {fields.map(col => {
              return <span></span>
            })}
          </div>
        </Col>
      })
    } else {
      return <Col></Col>
    }
  }
  render() {
    return (
      <Row gutter={24}>{this.getCards()}</Row>
    )
  }
}
export default CheckCard
src/tabviews/zshare/checkCard/index.scss
New file
@@ -0,0 +1,3 @@
.check-card-edit-box {
}
src/tabviews/zshare/fileupload/index.jsx
@@ -8,11 +8,6 @@
import Utils from '@/utils/utils.js'
import './index.scss'
// let Url = '/Upload'
// if (process.env.NODE_ENV === 'production') {
//   Url = document.location.origin + '/' + window.GLOB.service + 'zh-CN/Home/Upload'
// }
let service = ''
if (process.env.NODE_ENV === 'production') {
  service = document.location.origin + '/' + window.GLOB.service
@@ -22,7 +17,7 @@
class FileUpload extends Component {
  static propTpyes = {
    value: PropTypes.array,    // 按钮信息、表单列表
    value: PropTypes.array,    // 文件数组
    maxFile: PropTypes.any,    // 最大文件数
    fileType: PropTypes.string // 文件显示类型
  }
@@ -81,12 +76,6 @@
      duration: 5
    })
  }
  // getExtraData = () => {
  //   return {
  //     RootPath: 'Content/images/upload/'
  //   }
  // }
  shardupload = (params) => {
    let param = params.chunks.shift()
@@ -229,7 +218,6 @@
      chunkFileReader.readAsArrayBuffer(blobSlice.call(file, start, end))
    }
    // loadNext()
    return false
  }
@@ -262,16 +250,18 @@
      multiple: false,
      onChange: this.onChange,
      onRemove: this.onRemove,
      // data: this.getExtraData,
      beforeUpload: this.beforeUpload,
      className: uploadable
    }
    return (
      <Upload {...props}>
        <Button>
        {fileType !== 'picture-card' ? <Button>
          <Icon type="upload" /> 点击上传
        </Button>
        </Button> : null}
        {fileType === 'picture-card' ? <span style={{whiteSpace: 'nowrap'}}>
          <Icon type="upload" /> 点击上传
        </span> : null}
        {showprogress ? <Progress percent={percent} size="small" /> : null}
      </Upload>
    )
src/templates/modalconfig/checkCard/index.jsx
New file
@@ -0,0 +1,74 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
// import { fromJS } from 'immutable'
import { Col, Row } from 'antd'
import './index.scss'
class CheckCard extends Component {
  static propTpyes = {
    multiple: PropTypes.bool,    // 是否可多选
    ratio: PropTypes.string,     // 图片比例
    width: PropTypes.number,     // 宽度
    display: PropTypes.string,   // 显示为:text(文本)、picture(图片)
    fields: PropTypes.array,     // 字段集
    options: PropTypes.array,    // 数据列表
    onChange: PropTypes.func,    // 数据切换
  }
  state = {
    selectKeys: null,       // 选中数据id
  }
  UNSAFE_componentWillMount () {
  }
  UNSAFE_componentWillReceiveProps (nextProps) {
  }
  getCards = () => {
    const { display, width, options, fields, ratio } = this.props
    let paddingTop = '100%'
    if (ratio === '4:3') {
      paddingTop = '75%'
    } else if (ratio === '3:2') {
      paddingTop = '66.7%'
    } else if (ratio === '16:9') {
      paddingTop = '56.25%'
    }
    if (display !== 'picture') {
      return options.map(item => {
        return <Col span={width} key={item.key}>
          <div className="card-cell">
            {fields.map(col => {
              return <span key={col.key} style={{color: col.color, fontSize: col.fontSize + 'px', height: col.fontSize * 1.5 + 'px', textAlign: col.align}}>{item[col.field]}</span>
            })}
          </div>
        </Col>
      })
    } else {
      return options.map(item => {
        return <Col span={width} key={item.key}>
          <div className="card-pic-cell" style={{paddingTop, backgroundImage: `url(${item.$url})`}}>
          </div>
        </Col>
      })
    }
  }
  render() {
    return (
      <div className="check-card-edit-box" style={{marginTop: '10px'}}>
        <Row gutter={12}>{this.getCards()}</Row>
      </div>
    )
  }
}
export default CheckCard
src/templates/modalconfig/checkCard/index.scss
New file
@@ -0,0 +1,19 @@
.check-card-edit-box {
  .card-cell {
    border: 1px solid #bcbcbc;
    border-radius: 4px;
    padding: 6px;
    span {
      display: block;
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }
  }
  .card-pic-cell {
    border: 1px solid #bcbcbc;
    border-radius: 4px;
    background-size: cover;
    background-position: center;
  }
}
src/templates/modalconfig/dragelement/card.jsx
@@ -2,12 +2,14 @@
import { useDrag, useDrop } from 'react-dnd'
import { Icon, Select, DatePicker, Input, InputNumber, Button, Popover, Switch, Radio, Checkbox } from 'antd'
import moment from 'moment'
import CheckCard from '../checkCard'
import './index.scss'
const { MonthPicker } = DatePicker
const { TextArea } = Input
const Card = ({ id, card, cols, moveCard, findCard, editCard, closeCard, copyCard, hasDrop }) => {
const Card = ({ id, card, cols, moveCard, findCard, editCard, closeCard, copyCard }) => {
  const originalIndex = findCard(id).index
  const [{ isDragging }, drag] = useDrag({
    item: { type: 'form', id, originalIndex },
@@ -18,9 +20,11 @@
  const [, drop] = useDrop({
    accept: 'form',
    canDrop: () => true,
    drop: ({ id: draggedId, originalIndex }) => {
    drop: (item) => {
      const { id: draggedId, originalIndex } = item
      if (originalIndex === undefined) {
        hasDrop(card)
        item.dropTargetId = id
      } else if (draggedId) {
        if (draggedId !== id) {
          const { index: overIndex } = findCard(id)
@@ -58,7 +62,13 @@
  }
  let labelCol = 'ant-col-sm-8'
  let wrapCol = 'ant-col-sm-16'
  if (card.type === 'textarea') {
  let isEntireLine = false
  if (card.entireLine === 'true' || ['textarea', 'hint', 'checkcard'].includes(card.type)) {
    isEntireLine = true
  }
  if (isEntireLine) {
    if (cols === '2') {
      labelCol = 'ant-col-sm-4'
      wrapCol = 'ant-col-sm-20'
@@ -108,6 +118,10 @@
      <Checkbox value="C">C</Checkbox>
      <Checkbox value="D">D</Checkbox>
    </Checkbox.Group>)
  } else if (card.type === 'hint') {
    formItem = <div style={{marginTop: '10px', color: 'rgba(0, 0, 0, 0.85)'}}>{card.message}</div>
  } else if (card.type === 'checkcard') {
    formItem = <CheckCard width={card.width} ratio={card.ratio} display={card.display} fields={card.fields} options={card.options} />
  }
  return (
@@ -122,7 +136,9 @@
        <div ref={node => drag(drop(node))}>
          {<div className="ant-row ant-form-item">
            <div className={'ant-col ant-form-item-label ant-col-xs-24 ' + labelCol}>
              <label title={card.label}>{card.label}</label>
              {card.label ? <label className={card.required === 'true' ? 'required' : ''}>{card.tooltip ?
                <Icon type="question-circle" /> : null}
                {card.label}</label> : null}
            </div>
            <div className={'ant-col ant-form-item-control-wrapper ant-col-xs-24 ' + wrapCol}>
              {formItem}
src/templates/modalconfig/dragelement/index.jsx
@@ -8,8 +8,6 @@
import './index.scss'
const Container = ({list, group, setting, placeholder, handleList, handleForm, closeForm }) => {
  let target = null
  const [cards, setCards] = useState(list)
  const moveCard = (id, atIndex) => {
    const { card, index } = findCard(id)
@@ -39,7 +37,7 @@
  const editCard = id => {
    const { card } = findCard(id)
    handleForm(card, 'edit')
    handleForm(card)
  }
  const closeCard = id => {
@@ -48,12 +46,34 @@
  }
  const copyCard = id => {
    const { card } = findCard(id)
    handleForm(card, 'copy')
  }
  const hasDrop = (item) => {
    target = item
    const { card, index: overIndex } = findCard(id)
    let _card = fromJS(card).toJS()
    _card.uuid = Utils.getuuid()
    _card.focus = true
    // 复制到剪切板
    let oInput = document.createElement('input')
    let val = JSON.parse(JSON.stringify(_card))
    val.copyType = 'form'
    oInput.value = window.btoa(window.encodeURIComponent(JSON.stringify(val)))
    document.body.appendChild(oInput)
    oInput.select()
    document.execCommand('Copy')
    oInput.className = 'oInput'
    oInput.style.display = 'none'
    document.body.removeChild(oInput)
    const _cards = update(cards, { $splice: [[overIndex + 1, 0, _card]] })
    setCards(_cards)
    if (!group) {
      handleList(_cards, null, null, _card)
    } else {
      handleList(_cards, group, null, _card)
    }
  }
  const [, drop] = useDrop({
@@ -79,17 +99,17 @@
      newcard.required = 'true'
      newcard.focus = true
      let targetId = cards.length > 0 ? cards[cards.length - 1].uuid : 0
      if (target) {
        targetId = target.uuid
      let targetId = '0'
      if (item.dropTargetId) {
        targetId = item.dropTargetId
      } else if (cards.length > 0) {
        targetId = cards[cards.length - 1].uuid
      }
      const { index: overIndex } = findCard(`${targetId}`)
      let targetIndex = overIndex
      const { index: overIndex } = findCard(`${targetId}`) // cards为空时 overIndex 为 -1
      const _cards = update(cards, { $splice: [[overIndex + 1, 0, newcard]] })
      targetIndex++
      const _cards = update(cards, { $splice: [[targetIndex, 0, newcard]] })
      setCards(_cards)
      if (!group) {
@@ -97,8 +117,6 @@
      } else {
        handleList(_cards, group, null, newcard)
      }
      target = null
    }
  })
@@ -106,8 +124,14 @@
  
  return (
    <div ref={drop} className="ant-row modal-fields-row">
      {cards.map(card => (
        <Col key={card.uuid} className={card.type === 'textarea' ? 'textarea' + setting.cols : ''} span={card.type !== 'textarea' ? _cols : 24}>
      {cards.map(card => {
        let isEntireLine = false
        if (card.entireLine === 'true' || ['textarea', 'hint', 'checkcard'].includes(card.type)) {
          isEntireLine = true
        }
        return <Col key={card.uuid} className={isEntireLine ? 'textarea' + setting.cols : ''} span={isEntireLine ? 24 : _cols}>
          <Card
            id={card.uuid}
            cols={setting.cols}
@@ -117,10 +141,9 @@
            closeCard={closeCard}
            copyCard={copyCard}
            findCard={findCard}
            hasDrop={hasDrop}
          />
        </Col>
      ))}
      })}
      {cards.length === 0 &&
        <div className="modal-drawarea-placeholder">
          {placeholder}
src/templates/modalconfig/index.jsx
@@ -49,7 +49,6 @@
    dict: CommonDict,      // 字典
    config: null,          // 页面配置,包括模板类型、模态框设置、添加表名、表单列表
    visible: false,        // 表单编辑模态框,显示控制
    modalType: null,       // 表单编辑类型,编辑或复制
    tableVisible: false,   // 数据表字段列表模态框,显示控制
    tableColumns: [],      // 表格字段名列表
    fields: null,          // 表单,可选字段(去重后)
@@ -352,32 +351,9 @@
   * 2、保存编辑项-card
   * 3、设置编辑参数项-formlist
   */
  handleForm = (_card, type) => {
  handleForm = (_card) => {
    const {menu, tabConfig, subTabConfig} = this.props
    let card = JSON.parse(JSON.stringify(_card))
    if (type === 'copy') {
      card.originUuid = card.uuid
      card.uuid = Utils.getuuid()
      card.focus = true
      // 复制到剪切板
      let oInput = document.createElement('input')
      let val = JSON.parse(JSON.stringify(card))
      val.copyType = 'form'
      val.uuid = Utils.getuuid()
      delete val.originUuid
      oInput.value = window.btoa(window.encodeURIComponent(JSON.stringify(val)))
      document.body.appendChild(oInput)
      oInput.select()
      document.execCommand('Copy')
      oInput.className = 'oInput'
      oInput.style.display = 'none'
      document.body.removeChild(oInput)
    }
    const { config } = this.state
    let _inputfields = []
    let _linkableFields = []
@@ -472,7 +448,6 @@
    this.setState({
      visible: true,
      modalType: type,
      card: card,
      formlist: getModalForm(card, _inputfields, _linkableFields, _linksupFields, !!this.props.editTab, roleList)
    })
@@ -485,70 +460,14 @@
   * 3、通过loading刷新
   */
  handleSubmit = () => {
    const { card, modalType } = this.state
    this.formRef.handleConfirm().then(res => {
      let _config = JSON.parse(JSON.stringify(this.state.config))
      let fieldrepet = false // 字段重复
      let labelrepet = false // 提示文字重复
      if (modalType === 'copy' && card.originUuid) {
        if (_config.groups.length > 0) {
          _config.groups = _config.groups.map(group => {
            let _index = null
            group.sublist.forEach((item, index) => {
              if (item.uuid === card.originUuid) {
                _index = index
              }
              if (item.uuid !== res.uuid && item.field === res.field) {
                fieldrepet = true
              } else if (item.uuid !== res.uuid && item.label === res.label) {
                labelrepet = true
              }
            })
            if (_index !== null) {
              group.sublist.splice(_index + 1, 0, res)
            }
            return group
          })
        } else {
          let _index = null
          _config.fields.forEach((item, index) => {
            if (item.uuid === card.originUuid) {
              _index = index
            }
            if (item.uuid !== res.uuid && item.field === res.field) {
              fieldrepet = true
            } else if (item.uuid !== res.uuid && item.label === res.label) {
              labelrepet = true
            }
          })
          _config.fields.splice(_index + 1, 0, res)
        }
      } else {
        if (_config.groups.length > 0) {
          _config.groups.forEach(group => {
            group.sublist = group.sublist.map(item => {
              if (item.uuid !== res.uuid && item.field === res.field) {
                fieldrepet = true
              } else if (item.uuid !== res.uuid && item.label === res.label) {
                labelrepet = true
              }
              if (item.uuid === res.uuid) {
                return res
              } else {
                return item
              }
            })
          })
        } else {
          _config.fields = _config.fields.map(item => {
      if (_config.groups.length > 0) {
        _config.groups.forEach(group => {
          group.sublist = group.sublist.map(item => {
            if (item.uuid !== res.uuid && item.field === res.field) {
              fieldrepet = true
            } else if (item.uuid !== res.uuid && item.label === res.label) {
@@ -561,7 +480,21 @@
              return item
            }
          })
        }
        })
      } else {
        _config.fields = _config.fields.map(item => {
          if (item.uuid !== res.uuid && item.field === res.field) {
            fieldrepet = true
          } else if (item.uuid !== res.uuid && item.label === res.label) {
            labelrepet = true
          }
          if (item.uuid === res.uuid) {
            return res
          } else {
            return item
          }
        })
      }
      if (fieldrepet) {
@@ -607,7 +540,6 @@
            this.setState({
              sqlVerifing: false,
              config: _config,
              modalType: null,
              card: null,
              visible: false
            })
@@ -622,7 +554,6 @@
      } else {
        this.setState({
          config: _config,
          modalType: null,
          card: null,
          visible: false
        })
@@ -1299,9 +1230,10 @@
          </div>
        </DndProvider>
        <Modal
          title={this.state.modalType !== 'copy' ? this.state.dict['model.edit'] : this.state.dict['header.modal.form.copy']}
          title={this.state.dict['model.edit']}
          visible={this.state.visible}
          width={800}
          width={850}
          maskClosable={false}
          onCancel={this.editModalCancel}
          onOk={this.handleSubmit}
          confirmLoading={this.state.sqlVerifing}
src/templates/modalconfig/index.scss
@@ -198,6 +198,20 @@
                text-overflow: ellipsis;
                white-space: nowrap;
              }
              label.required::before {
                display: inline-block;
                margin-right: 4px;
                color: #f5222d;
                font-size: 14px;
                font-family: SimSun, sans-serif;
                line-height: 1;
                content: '*';
              }
              .anticon-question-circle {
                color: #c49f47;
                margin-right: 3px;
                line-height: 40px;
              }
            }
            .ant-form-item-control-wrapper {
              .ant-select {
src/templates/modalconfig/source.jsx
@@ -158,6 +158,12 @@
  },
  {
    type: 'form',
    label: '提示',
    subType: 'hint',
    url: ''
  },
  {
    type: 'form',
    label: CommonDict['model.form.color'],
    subType: 'color',
    url: ''
src/templates/sharecomponent/treesettingcomponent/settingform/datasource/index.jsx
@@ -426,7 +426,7 @@
            </Col>
            <Col span={12}>
              <Form.Item label={
                <Tooltip placement="topLeft" title={'每行分为24份,树形比例可设置为2-12(最大50%)'}>
                <Tooltip placement="topLeft" title={'栅格布局,每行等分为24列,树形比例可设置为2-12(最大50%)'}>
                  <Icon type="question-circle" />
                  宽度
                </Tooltip>
src/templates/zshare/createinterface/index.jsx
@@ -360,7 +360,7 @@
        type: 'radio',
        key: 'TryType',
        label: '事务',
        initval: 'N',
        initval: 'Y',
        required: true,
        options: [{
          value: 'Y',
@@ -569,14 +569,9 @@
    }).then(res => {
      if (res === false) return res
      if (window.GLOB.mainSystemApi) {
        _mainParam.rduri = window.GLOB.mainSystemApi
        return Api.getLocalConfig(_mainParam)
      }
      return 'success'
      return Api.getCloudConfig(_mainParam)
    }).then(res => {
      if (res === false || res === 'success') return res
      if (res === false) return res
      if (!res.status) {
        notification.warning({
src/templates/zshare/formconfig.jsx
@@ -226,7 +226,7 @@
      min: 2,
      max: 12,
      label: '宽度',
      tooltip: '每行分为24份,树形比例可设置为2-12(最大50%)',
      tooltip: '栅格布局,每行等分为24列,树形比例可设置为2-12(最大50%)',
      initVal: setting.width || 5,
      required: true
    },
@@ -529,7 +529,7 @@
      min: 1,
      max: 24,
      label: Formdict['header.form.ratio'],
      tooltip: '每行分为24份,比例可设置为1-24',
      tooltip: '栅格布局,每行等分为24列。',
      initVal: card.ratio,
      required: false
    },
@@ -1356,7 +1356,7 @@
      max: 24,
      decimal: 0,
      label: '图表宽度',
      tooltip: '每行等分为24列,24即为100%。',
      tooltip: '栅格布局,每行等分为24列。',
      initVal: card.width || 24,
      required: true
    },
@@ -1398,7 +1398,7 @@
      max: card.widthType === 'absolute' ? 1000 : 24,
      decimal: 0,
      label: '卡片宽度',
      tooltip: '类型为比例时,范围1-24,24即为100%;类型为绝对值,范围50-1000。',
      tooltip: '类型为比例时,栅格布局,每行等分为24列;类型为绝对值,范围50-1000。',
      initVal: card.cardWidth || 6,
      hidden: true,
      required: true
@@ -1771,7 +1771,7 @@
    })
  }
  if (card.type === 'textarea' || card.type === 'fileupload' || card.type === 'multiselect') {
  if (card.type === 'textarea' || card.type === 'fileupload' || card.type === 'multiselect' || card.type === 'checkbox') {
    _fieldlength = 512
  }
@@ -1841,6 +1841,9 @@
        value: 'textarea',
        text: Formdict['model.form.textarea']
      }, {
        value: 'hint',
        text: '提示'
      }, {
        value: 'color',
        text: Formdict['model.form.color']
      }, {
@@ -1856,6 +1859,14 @@
      tooltip: '下拉多选与多选框,添加多个初始值请使用“,”号分隔。',
      initVal: card.initval || '',
      required: false
    },
    {
      type: 'textarea',
      key: 'message',
      label: '提示信息',
      initVal: card.message || '',
      required: true,
      readonly: false
    },
    {
      type: 'text',
@@ -1900,6 +1911,50 @@
      }]
    },
    {
      type: 'number',
      key: 'width',
      label: '卡片宽度',
      initVal: card.width || 4,
      tooltip: '栅格布局,每行等分为24列。',
      required: true
    },
    {
      type: 'text',
      key: 'cardValField',
      label: Formdict['header.form.valueField'],
      initVal: card.cardValField || 'Value',
      required: true,
      readonly: false
    },
    {
      type: 'text',
      key: 'urlField',
      label: '地址字段',
      initVal: card.urlField || '',
      required: true,
      readonly: false
    },
    {
      type: 'radio',
      key: 'ratio',
      label: '图片比例',
      initVal: card.ratio || '1:1',
      required: true,
      options: [{
        value: '1:1',
        text: '1:1'
      }, {
        value: '3:2',
        text: '3:2'
      }, {
        value: '4:3',
        text: '4:3'
      }, {
        value: '16:9',
        text: '16:9'
      }]
    },
    {
      type: 'radio',
      key: 'setAll',
      label: Formdict['header.form.setAll'],
@@ -1913,18 +1968,26 @@
      }]
    },
    {
      type: 'textarea',
      key: 'dataSource',
      label: Formdict['header.form.datasource'],
      initVal: card.dataSource || '',
      type: 'fields',
      key: 'fields',
      label: '字段集',
      initVal: card.fields || [],
      required: true,
      readonly: false
    },
    {
      type: 'options',
      key: 'options',
      label: '',
      label: '选项',
      initVal: card.options || [],
      required: true,
      readonly: false
    },
    {
      type: 'codemirror',
      key: 'dataSource',
      label: Formdict['header.form.datasource'],
      initVal: card.dataSource || '',
      required: true,
      readonly: false
    },
@@ -1972,6 +2035,20 @@
      }, {
        value: 'desc',
        text: Formdict['header.form.desc']
      }]
    },
    {
      type: 'radio',
      key: 'multiple',
      label: '可多选',
      initVal: card.multiple || 'false',
      required: true,
      options: [{
        value: 'true',
        text: '是'
      }, {
        value: 'false',
        text: '否'
      }]
    },
    {
@@ -2028,25 +2105,6 @@
        value: 'letter&number',
        text: Formdict['header.form.letter&number']
      }]
    },
    {
      type: 'select',
      key: 'supField',
      label: '上级表单',
      tooltip: '上级表单为下拉选择或联动菜单,设置上级表单后,该表单受控于上级菜单,注:受控关系在该表单隐藏时失效。',
      initVal: card.supField || '',
      required: false,
      readonly: false,
      options: linksupFields
    },
    {
      type: 'text',
      key: 'supvalue',
      label: '显示值',
      tooltip: '选择上级表单后,填写显示值,只有上级表单值与显示值相同时,该表单才会显示,注:多个值用逗号分隔。',
      initVal: card.supvalue || '',
      required: true,
      readonly: false
    },
    {
      type: 'select',
@@ -2140,7 +2198,7 @@
    {
      type: 'radio',
      key: 'writein',
      label: '写入',
      label: '执行运算',
      tooltip: '表单提交时,是否将该字段值写入默认sql语句中。',
      initVal: card.writein || 'true',
      options: [{
@@ -2193,13 +2251,41 @@
      }]
    },
    {
      type: 'select',
      key: 'supField',
      label: '上级表单',
      tooltip: '上级表单为下拉选择、联动菜单、单选框及多选框,添加后该表单显示及隐藏将受上级表单控制,注:受控关系在该表单隐藏时失效。',
      initVal: card.supField || '',
      required: false,
      readonly: false,
      options: linksupFields
    },
    {
      type: 'text',
      key: 'supvalue',
      label: '显示值',
      tooltip: '请填写显示值,只有上级表单值与显示值相同时,该表单才会显示,注:多个值用逗号分隔。',
      initVal: card.supvalue || '',
      required: true,
      readonly: false
    },
    {
      type: 'multiselect',
      key: 'linkSubField',
      label: Formdict['model.form.linkform'],
      tooltip: '在切换选项时会把信息自动填入关联的表单(文本或数字表单)中。',
      initVal: card.linkSubField || [],
      options: inputfields
    },
    {
      type: 'text',
      key: 'tooltip',
      label: '表单注释',
      tooltip: '鼠标悬浮于提示文字上方时,显示注释。',
      initVal: card.tooltip || '',
      required: false
    },
    {
      type: 'multiselect',
      key: 'blacklist',
      label: Formdict['header.form.blacklist'],
src/templates/zshare/modalform/datatable/index.jsx
New file
@@ -0,0 +1,368 @@
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import { is, fromJS } from 'immutable'
import { Table, Input, Popconfirm, Form, Icon, notification } from 'antd'
import Utils from '@/utils/utils.js'
import FileUpload from '@/tabviews/zshare/fileupload'
import './index.scss'
const EditableContext = React.createContext()
class EditableCell extends Component {
  getInput = (form) => {
    const { inputType } = this.props
    if (inputType === 'file') {
      return <FileUpload maxFile={1} fileType="picture-card"/>
    } else {
      return <Input onPressEnter={() => this.getValue(form)} />
    }
  }
  getValue = (form) => {
    const { record } = this.props
    form.validateFields((error, row) => {
      if (error) {
        return
      }
      if (row.$url && Array.isArray(row.$url)) {
        if (!row.$url[0]) {
          row.$url = ''
        } else if (row.$url[0].origin) {
          row.$url = row.$url[0].url || ''
        } else if (!row.$url[0].origin && row.$url[0].status === 'done' && row.$url[0].response) {
          row.$url = row.$url[0].response
        }
      }
      this.props.onSave({...record, ...row})
    })
  }
  renderCell = (form) => {
    const { getFieldDecorator } = form
    const {
      editing,
      dataIndex,
      title,
      record,
      inputType,
      index,
      children,
      onSave,
      ...restProps
    } = this.props;
    let _val = ''
    if (record && dataIndex) {
      _val = record[dataIndex]
    }
    if (dataIndex === '$url' && _val) {
      _val = [{
        uid: `10086`,
        name: _val.slice(_val.lastIndexOf('/') + 1),
        status: 'done',
        url: _val,
        origin: true
      }]
    } else if (dataIndex === '$url') {
      _val = []
    }
    return (
      <td {...restProps}>
        {editing ? (
          <Form.Item style={{ margin: 0 }}>
            {getFieldDecorator(dataIndex, {
              rules: [
                {
                  required: dataIndex === '$value',
                  message: `Please Input ${title}!`,
                },
              ],
              initialValue: _val,
            })(this.getInput(form))}
          </Form.Item>
        ) : (
          children
        )}
      </td>
    )
  }
  render() {
    return <EditableContext.Consumer>{this.renderCell}</EditableContext.Consumer>
  }
}
class EdiDataTable extends Component {
  static propTpyes = {
    dict: PropTypes.object,         // 字典项
    type: PropTypes.object,         // 数据类型,文本、图片
    fields: PropTypes.array,        // 字段集
    onChange: PropTypes.func        // 数据变化
  }
  UNSAFE_componentWillMount () {
    let data = this.props['data-__meta'].initialValue
    this.setState({
      data: data,
      columns: this.getCloumns()
    })
  }
  state = {
    data: [],
    editingKey: '',
    columns: []
  }
  UNSAFE_componentWillReceiveProps (nextProps) {
    if (!is(fromJS(this.props.fields), fromJS(nextProps.fields)) || !is(fromJS(this.props.type), fromJS(nextProps.type))) {
      this.setState({editingKey: ''}, () => {
        this.setState({
          columns: this.getCloumns()
        })
      })
    }
  }
  getCloumns = () => {
    const { type, fields } = this.props
    let columns = []
    if (type === 'picture') {
      columns.push({
        title: 'url',
        dataIndex: '$url',
        inputType: 'file',
        width: '40%',
        editable: true,
        render: (text) => {
          if (!text) return ''
          return <span style={{display: 'block', width: '70px', height: '70px'}}><img style={{width: '100%', height: '100%'}} src={text} alt="" /></span>
        }
      })
    } else {
      columns = fields.map(item => ({
        title: item.field,
        dataIndex: item.field,
        editable: true,
      }))
    }
    columns.unshift({
      title: 'Value',
      dataIndex: '$value',
      editable: true,
    })
    columns.push({
      title: 'operation',
      dataIndex: 'operation',
      width: '18%',
      render: (text, record) => {
        const { editingKey } = this.state
        const editable = this.isEditing(record)
        return editable ? (
          <span>
            <EditableContext.Consumer>
              {form => (
                <span onClick={() => this.save(form, record.key)} style={{ marginRight: 8 , color: '#1890ff', cursor: 'pointer'}}>
                  保存
                </span>
              )}
            </EditableContext.Consumer>
            <span style={{ color: '#1890ff', cursor: 'pointer'}} onClick={() => this.cancel(record.key)}>取消</span>
          </span>
        ) : (
          <div className={'operation-btn' + (editingKey !== '' ? ' disabled' : '')}>
            <span className="primary" onClick={() => {editingKey === '' && this.edit(record.key)}}><Icon type="edit" /></span>
            <span className="primary" onClick={() => {editingKey === '' && this.handleUpDown(record.key, 'up')}}><Icon type="arrow-up" /></span>
            <span className="danger" onClick={() => {editingKey === '' && this.handleUpDown(record.key, 'down')}}><Icon type="arrow-down" /></span>
            {editingKey === '' ? <Popconfirm
              overlayClassName="popover-confirm"
              title={this.props.dict['model.query.delete']}
              onConfirm={() => this.handleDelete(record.key)
            }>
              <span className="danger"><Icon type="delete" /></span>
            </Popconfirm> : null}
            {editingKey !== '' ? <span className="danger"><Icon type="delete" /></span> : null}
          </div>
        )
      }
    })
    return columns
  }
  isEditing = record => record.key === this.state.editingKey
  cancel = () => {
    this.setState({ editingKey: '' })
  }
  onSave = (record) => {
    const newData = [...this.state.data]
    const index = newData.findIndex(item => record.key === item.key)
    if (index > -1) {
      newData.splice(index, 1, record)
      this.setState({ data: newData, editingKey: '' }, () => {
        this.props.onChange(newData)
      })
    }
  }
  handleDelete = (key) => {
    const { data } = this.state
    let _data = data.filter(item => key !== item.key)
    this.setState({
      data: _data
    }, () => {
      this.props.onChange(_data)
    })
  }
  handleUpDown = (key, direction) => {
    let _data = fromJS(this.state.data).toJS()
    const index = _data.findIndex(item => key === item.key)
    if ((index === 0 && direction === 'up') || (index === _data.length - 1 && direction === 'down')) {
      return
    }
    if (direction === 'up') {
      _data.splice(index - 1, 0, ..._data.splice(index, 1))
    } else {
      _data.splice(index + 1, 0, ..._data.splice(index, 1))
    }
    this.setState({
      data: _data
    }, () => {
      this.props.onChange(_data)
    })
  }
  save(form, key) {
    form.validateFields((error, row) => {
      if (error) {
        return;
      }
      if (row.$url && Array.isArray(row.$url)) {
        if (!row.$url[0]) {
          row.$url = ''
        } else if (row.$url[0].origin) {
          row.$url = row.$url[0].url || ''
        } else if (!row.$url[0].origin && row.$url[0].status === 'done' && row.$url[0].response) {
          row.$url = row.$url[0].response
        }
      }
      const newData = [...this.state.data]
      const index = newData.findIndex(item => key === item.key)
      if (index > -1) {
        const item = newData[index]
        newData.splice(index, 1, {
          ...item,
          ...row,
        })
        this.setState({ data: newData, editingKey: '' }, () => {
          this.props.onChange(newData)
        })
      } else {
        newData.push(row);
        this.setState({ data: newData, editingKey: '' }, () => {
          this.props.onChange(newData)
        })
      }
    })
  }
  handleAdd = () => {
    const { fields, type } = this.props
    if (this.state.editingKey) {
      notification.warning({
        top: 92,
        message: '请保存编辑中的元素!',
        duration: 5
      })
      return
    }
    let item = { key: Utils.getuuid(), $value: `${this.state.data.length + 1}` }
    if (type === 'picture') {
      item.$url = ''
    } else {
      fields.forEach(f => {
        item[f.field] = `${this.state.data.length + 1}`
      })
    }
    let data = [...this.state.data, item]
    this.setState({ data }, () => {
      this.props.onChange(data)
    })
  }
  edit(key) {
    this.setState({ editingKey: key })
  }
  render() {
    const components = {
      body: {
        cell: EditableCell,
      },
    }
    const columns = this.state.columns.map(col => {
      if (!col.editable) {
        return col
      }
      return {
        ...col,
        onCell: record => ({
          record,
          dataIndex: col.dataIndex,
          inputType: col.inputType,
          title: col.title,
          editing: this.isEditing(record),
          onSave: this.onSave,
        }),
      }
    })
    let addable = false
    if (this.props.type === 'picture') {
      addable = true
    } else if (this.props.fields && this.props.fields.length > 0) {
      addable = true
    }
    return (
      <EditableContext.Provider value={this.props.form}>
        <div className="modal-card-data-table">
          {addable ? <Icon className="add-row" type="plus" onClick={this.handleAdd} /> : null}
          <Table
            components={components}
            bordered
            dataSource={this.state.data}
            columns={columns}
            rowClassName="editable-row"
            pagination={false}
          />
        </div>
      </EditableContext.Provider>
    )
  }
}
export default Form.create()(EdiDataTable)
src/templates/zshare/modalform/datatable/index.scss
New file
@@ -0,0 +1,57 @@
.modal-card-data-table {
  .add-row {
    position: absolute;
    z-index: 1;
    right: 10px;
    top: -30px;
    padding: 5px;
    font-size: 18px;
    color: #26C281;
  }
  .editable-row {
    .ant-form-explain {
      position: absolute;
      font-size: 12px;
      margin-top: -4px;
    }
    .ant-form-item-control {
      line-height: 1;
    }
    .fileupload-form-container .ant-upload-list-picture-card .ant-upload-list-item {
      width: 70px;
      height: 70px;
      margin: 0;
      padding: 2px;
      .ant-upload-list-item-info > span {
        height: 100%;
      }
    }
    .fileupload-form-container .ant-upload.ant-upload-select-picture-card {
      width: 70px;
      height: 70px;
    }
  }
  .operation-btn {
    span {
      margin-right: 7px;
      cursor: pointer;
    }
    .primary {
      color: #1890ff;
    }
    .danger {
      color: #ff4d4f;
    }
  }
  .operation-btn.disabled {
    span {
      cursor: default;
    }
    .primary {
      color: rgba(0, 0, 0, .25);
    }
    .danger {
      color: rgba(0, 0, 0, .25);
    }
  }
}
src/templates/zshare/modalform/fieldtable/index.jsx
New file
@@ -0,0 +1,308 @@
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import { fromJS } from 'immutable'
import { Table, Input, InputNumber, Popconfirm, Form, Icon, notification, Select } from 'antd'
import ColorSketch from '@/mob/colorsketch'
import Utils from '@/utils/utils.js'
import './index.scss'
const EditableContext = React.createContext()
class EditableCell extends Component {
  getInput = (form) => {
    const { inputType } = this.props
    if (inputType === 'number') {
      return <InputNumber min={12} max={50} precision={0} onPressEnter={() => this.getValue(form)} />
    } else if (inputType === 'color') {
      return <ColorSketch />
    } else if (inputType === 'select') {
      return <Select>
        <Select.Option key="left" value="left"> left </Select.Option>
        <Select.Option key="center" value="center"> center </Select.Option>
        <Select.Option key="right" value="right"> right </Select.Option>
        <Select.Option key="justify" value="justify"> justify </Select.Option>
      </Select>
    } else {
      return <Input onPressEnter={() => this.getValue(form)} />
    }
  }
  getValue = (form) => {
    const { record } = this.props
    form.validateFields((error, row) => {
      if (error) {
        return
      }
      this.props.onSave({...record, ...row})
    })
  }
  renderCell = (form) => {
    const { getFieldDecorator } = form
    const {
      editing,
      dataIndex,
      title,
      inputType,
      record,
      index,
      children,
      onSave,
      ...restProps
    } = this.props;
    return (
      <td {...restProps}>
        {editing ? (
          <Form.Item style={{ margin: 0 }}>
            {getFieldDecorator(dataIndex, {
              rules: [
                {
                  required: true,
                  message: `Please Input ${title}!`,
                },
              ],
              initialValue: record[dataIndex],
            })(this.getInput(form))}
          </Form.Item>
        ) : (
          children
        )}
      </td>
    )
  }
  render() {
    return <EditableContext.Consumer>{this.renderCell}</EditableContext.Consumer>
  }
}
class EdiFieldsTable extends Component {
  static propTpyes = {
    dict: PropTypes.object,         // 字典项
    onChange: PropTypes.func        // 数据变化
  }
  UNSAFE_componentWillMount () {
    let data = this.props['data-__meta'].initialValue
    this.setState({
      data: data
    })
  }
  state = {
    data: [],
    editingKey: '',
    columns: [
      {
        title: '字段名',
        dataIndex: 'field',
        inputType: 'input',
        editable: true,
      },
      {
        title: '字体颜色',
        dataIndex: 'color',
        inputType: 'color',
        editable: true,
        render: (text, record) => {
          return <span style={{color: text}}>示例</span>
        }
      },
      {
        title: '字体大小',
        dataIndex: 'fontSize',
        inputType: 'number',
        editable: true,
      },
      {
        title: '对齐方式',
        dataIndex: 'align',
        inputType: 'select',
        editable: true,
      },
      {
        title: 'operation',
        dataIndex: 'operation',
        width: '18%',
        render: (text, record) => {
          const { editingKey } = this.state
          const editable = this.isEditing(record)
          return editable ? (
            <span>
              <EditableContext.Consumer>
                {form => (
                  <span onClick={() => this.save(form, record.key)} style={{ marginRight: 8 , color: '#1890ff', cursor: 'pointer'}}>
                    保存
                  </span>
                )}
              </EditableContext.Consumer>
              <span style={{ color: '#1890ff', cursor: 'pointer'}} onClick={() => this.cancel(record.key)}>取消</span>
            </span>
          ) : (
            <div className={'operation-btn' + (editingKey !== '' ? ' disabled' : '')}>
              <span className="primary" onClick={() => {editingKey === '' && this.edit(record.key)}}><Icon type="edit" /></span>
              <span className="primary" onClick={() => {editingKey === '' && this.handleUpDown(record.key, 'up')}}><Icon type="arrow-up" /></span>
              <span className="danger" onClick={() => {editingKey === '' && this.handleUpDown(record.key, 'down')}}><Icon type="arrow-down" /></span>
              {editingKey === '' ? <Popconfirm
                overlayClassName="popover-confirm"
                title={this.props.dict['model.query.delete']}
                onConfirm={() => this.handleDelete(record.key)
              }>
                <span className="danger"><Icon type="delete" /></span>
              </Popconfirm> : null}
              {editingKey !== '' ? <span className="danger"><Icon type="delete" /></span> : null}
            </div>
          )
        },
      },
    ]
  }
  isEditing = record => record.key === this.state.editingKey
  cancel = () => {
    this.setState({ editingKey: '' })
  }
  onSave = (record) => {
    const newData = [...this.state.data]
    const index = newData.findIndex(item => record.key === item.key)
    if (index > -1) {
      newData.splice(index, 1, record)
      this.setState({ data: newData, editingKey: '' }, () => {
        this.props.onChange(newData)
      })
    }
  }
  handleDelete = (key) => {
    const { data } = this.state
    let _data = data.filter(item => key !== item.key)
    this.setState({
      data: _data
    }, () => {
      this.props.onChange(_data)
    })
  }
  handleUpDown = (key, direction) => {
    let _data = fromJS(this.state.data).toJS()
    const index = _data.findIndex(item => key === item.key)
    if ((index === 0 && direction === 'up') || (index === _data.length - 1 && direction === 'down')) {
      return
    }
    if (direction === 'up') {
      _data.splice(index - 1, 0, ..._data.splice(index, 1))
    } else {
      _data.splice(index + 1, 0, ..._data.splice(index, 1))
    }
    this.setState({
      data: _data
    }, () => {
      this.props.onChange(_data)
    })
  }
  save(form, key) {
    form.validateFields((error, row) => {
      if (error) {
        return;
      }
      const newData = [...this.state.data]
      const index = newData.findIndex(item => key === item.key)
      if (index > -1) {
        const item = newData[index]
        newData.splice(index, 1, {
          ...item,
          ...row,
        })
        this.setState({ data: newData, editingKey: '' }, () => {
          this.props.onChange(newData)
        })
      } else {
        newData.push(row);
        this.setState({ data: newData, editingKey: '' }, () => {
          this.props.onChange(newData)
        })
      }
    })
  }
  handleAdd = () => {
    if (this.state.editingKey) {
      notification.warning({
        top: 92,
        message: '请保存编辑中的元素!',
        duration: 5
      })
      return
    }
    let item = {
      key: Utils.getuuid(),
      field: `field${this.state.data.length + 1}`,
      color: 'rgba(0, 0, 0, 0.85)',
      align: 'left',
      fontSize: 14,
    }
    let data = [...this.state.data, item]
    this.setState({ data }, () => {
      this.props.onChange(data)
    })
  }
  edit(key) {
    this.setState({ editingKey: key })
  }
  render() {
    const components = {
      body: {
        cell: EditableCell,
      },
    }
    const columns = this.state.columns.map(col => {
      if (!col.editable) {
        return col
      }
      return {
        ...col,
        onCell: record => ({
          record,
          inputType: col.inputType,
          dataIndex: col.dataIndex,
          title: col.title,
          editing: this.isEditing(record),
          onSave: this.onSave,
        }),
      }
    })
    return (
      <EditableContext.Provider value={this.props.form}>
        <div className="modal-card-data-table">
          {this.state.data.length < 3 ? <Icon className="add-row" type="plus" onClick={this.handleAdd} /> : null}
          <Table
            components={components}
            bordered
            dataSource={this.state.data}
            columns={columns}
            rowClassName="editable-row"
            pagination={false}
          />
        </div>
      </EditableContext.Provider>
    )
  }
}
export default Form.create()(EdiFieldsTable)
src/templates/zshare/modalform/fieldtable/index.scss
New file
@@ -0,0 +1,52 @@
.modal-card-data-table {
  .add-row {
    position: absolute;
    z-index: 1;
    right: 10px;
    top: -30px;
    padding: 5px;
    font-size: 18px;
    color: #26C281;
  }
  .editable-row {
    .ant-form-explain {
      position: absolute;
      font-size: 12px;
      margin-top: -4px;
    }
    .color-sketch-block {
      width: 200px;
      position: relative;
      top: 2px;
    }
    .ant-select {
      width: 80px;
    }
  }
  .operation-btn {
    span {
      margin-right: 10px;
      cursor: pointer;
    }
    .primary {
      color: #1890ff;
    }
    .danger {
      color: #ff4d4f;
    }
  }
  .operation-btn.disabled {
    span {
      cursor: default;
    }
    .primary {
      color: rgba(0, 0, 0, .25);
    }
    .danger {
      color: rgba(0, 0, 0, .25);
    }
  }
  .ant-empty {
    margin: 0;
  }
}
src/templates/zshare/modalform/index.jsx
@@ -6,27 +6,32 @@
import { dateOptions } from '@/utils/option.js'
import Utils from '@/utils/utils.js'
import EditTable from './modaleditable'
import DataTable from './datatable'
import FieldsTable from './fieldtable'
import CodeMirror from '@/templates/zshare/codemirror'
import './index.scss'
const { TextArea } = Input
const modalTypeOptions = {
  text: ['initval', 'readonly', 'required', 'hidden', 'readin', 'fieldlength', 'regular', 'interception', 'entireLine'],
  number: ['initval', 'readonly', 'hidden', 'decimal', 'min', 'max', 'readin', 'entireLine'],
  select: ['initval', 'readonly', 'required', 'hidden', 'readin', 'resourceType', 'setAll', 'linkSubField', 'entireLine'],
  checkbox: ['initval', 'readonly', 'required', 'hidden', 'readin', 'resourceType', 'linkSubField', 'entireLine'],
  radio: ['initval', 'readonly', 'required', 'hidden', 'readin', 'resourceType', 'linkSubField', 'entireLine'],
  checkcard: ['initval', 'readonly', 'required', 'hidden', 'readin', 'resourceType', 'linkSubField', 'display'],
  multiselect: ['initval', 'readonly', 'required', 'hidden', 'readin', 'resourceType', 'fieldlength', 'entireLine'],
  link: ['initval', 'readonly', 'required', 'hidden', 'readin', 'resourceType', 'setAll', 'linkField', 'entireLine'],
  fileupload: ['readonly', 'required', 'readin', 'fieldlength', 'maxfile', 'fileType', 'entireLine'],
  switch: ['initval', 'openVal', 'closeVal', 'readonly', 'required', 'hidden', 'readin', 'entireLine'],
  date: ['initval', 'readonly', 'required', 'hidden', 'readin', 'entireLine'],
  datemonth: ['initval', 'readonly', 'required', 'hidden', 'readin', 'entireLine'],
  datetime: ['initval', 'readonly', 'required', 'hidden', 'readin', 'entireLine'],
  textarea: ['initval', 'readonly', 'required', 'hidden', 'readin', 'fieldlength', 'maxRows', 'encryption', 'interception'],
  color: ['readonly', 'required', 'hidden', 'readin', 'entireLine'],
  funcvar: ['hidden'],
  linkMain: ['readonly', 'required', 'hidden', 'fieldlength', 'entireLine']
  text: ['initval', 'readonly', 'required', 'hidden', 'readin', 'fieldlength', 'regular', 'interception', 'entireLine', 'tooltip'],
  number: ['initval', 'readonly', 'hidden', 'decimal', 'min', 'max', 'readin', 'entireLine', 'tooltip'],
  select: ['initval', 'readonly', 'required', 'hidden', 'readin', 'resourceType', 'setAll', 'linkSubField', 'entireLine', 'tooltip'],
  checkbox: ['initval', 'readonly', 'required', 'hidden', 'readin', 'resourceType', 'entireLine', 'tooltip'],
  radio: ['initval', 'readonly', 'required', 'hidden', 'readin', 'resourceType', 'linkSubField', 'entireLine', 'tooltip'],
  checkcard: ['initval', 'readonly', 'required', 'hidden', 'readin', 'resourceType', 'linkSubField', 'fieldlength', 'display', 'tooltip', 'width', 'multiple'],
  multiselect: ['initval', 'readonly', 'required', 'hidden', 'readin', 'resourceType', 'fieldlength', 'entireLine', 'tooltip'],
  link: ['initval', 'readonly', 'required', 'hidden', 'readin', 'resourceType', 'setAll', 'linkField', 'entireLine', 'tooltip'],
  fileupload: ['readonly', 'required', 'readin', 'fieldlength', 'maxfile', 'fileType', 'entireLine', 'tooltip'],
  switch: ['initval', 'openVal', 'closeVal', 'readonly', 'required', 'hidden', 'readin', 'entireLine', 'tooltip'],
  date: ['initval', 'readonly', 'required', 'hidden', 'readin', 'entireLine', 'tooltip'],
  datemonth: ['initval', 'readonly', 'required', 'hidden', 'readin', 'entireLine', 'tooltip'],
  datetime: ['initval', 'readonly', 'required', 'hidden', 'readin', 'entireLine', 'tooltip'],
  textarea: ['initval', 'readonly', 'required', 'hidden', 'readin', 'fieldlength', 'maxRows', 'encryption', 'interception', 'tooltip'],
  color: ['readonly', 'required', 'hidden', 'readin', 'entireLine', 'tooltip'],
  hint: ['label', 'type', 'blacklist', 'message'],
  funcvar: [],
  linkMain: ['readonly', 'required', 'hidden', 'fieldlength', 'entireLine', 'tooltip']
}
class MainSearch extends Component {
@@ -41,6 +46,8 @@
    openType: null,
    resourceType: null,
    supField: '',
    display: 'text',
    cFields: [],
    formlist: null,
    linkSubFields: null
  }
@@ -51,11 +58,17 @@
    let type = ''
    let resourceType = ''
    let supField = ''
    let display = ''
    let cFields = []
    let linkSubFields = []
    formlist.forEach(cell => {
      if (cell.key === 'type') {
        type = cell.initVal
      } else if (cell.key === 'display') {
        display = cell.initVal
      } else if (cell.key === 'fields') {
        cFields = cell.initVal
      } else if (cell.key === 'resourceType') {
        resourceType = cell.initVal
      } else if (cell.key === 'linkSubField') {
@@ -73,11 +86,13 @@
      }
    })
    
    let _options = this.getOptions(type, resourceType, supField)
    let _options = this.getOptions(type, resourceType, supField, display)
    this.setState({
      openType: type,
      supField: supField,
      display: display,
      cFields: cFields,
      resourceType: resourceType,
      linkSubFields: linkSubFields,
      formlist: formlist.map(form => {
@@ -95,6 +110,11 @@
          form.type = 'number'
          form.initVal = form.initVal || 0
          form.required = true
        } else if (form.key === 'label') {
          form.required = true
          if (type === 'hint') {
            form.required = false
          }
        }
        form.show = _options.includes(form.key)
@@ -116,14 +136,30 @@
    }
  }
  getOptions = (type, resourceType, supField) => {
  getOptions = (type, resourceType, supField, display) => {
    let _options = ['label', 'field', 'type', 'blacklist', 'writein', ...fromJS(modalTypeOptions[type]).toJS()]
    if (['multiselect', 'select', 'link', 'radio', 'checkbox', 'checkcard'].includes(type)) {
    if (type === 'hint') {
      _options = fromJS(modalTypeOptions[type]).toJS()
    } else if (['multiselect', 'select', 'link', 'radio', 'checkbox'].includes(type)) {
      if (resourceType === '0') {        // 自定义资源
        _options = [..._options, 'options']
        _options.push('options')
      } else if (resourceType === '1') { // 数据源
        _options = [..._options, 'dataSource', 'valueField', 'valueText', 'orderBy', 'orderType', 'database']
        _options.push('dataSource', 'valueField', 'valueText', 'orderBy', 'orderType', 'database')
      }
    } else if (type === 'checkcard') {
      if (display === 'picture') {
        if (resourceType === '0') {        // 自定义资源
          _options.push('options', 'ratio')
        } else if (resourceType === '1') { // 数据源
          _options.push('dataSource', 'cardValField', 'urlField', 'orderBy', 'orderType', 'database', 'ratio')
        }
      } else {
        if (resourceType === '0') {        // 自定义资源
          _options.push('options', 'fields')
        } else if (resourceType === '1') { // 数据源
          _options.push('dataSource', 'cardValField', 'fields', 'orderBy', 'orderType', 'database')
        }
      }
    }
@@ -140,7 +176,7 @@
  openTypeChange = (key, value) => {
    if (key === 'type') {
      let _options = this.getOptions(value, this.state.resourceType, this.state.supField)
      let _options = this.getOptions(value, this.state.resourceType, this.state.supField, this.state.display)
      let fieldValue = {}
      
      this.setState({
@@ -192,7 +228,13 @@
            if (form.show) {
              fieldValue.linkSubField = form.initVal
            }
          } else if (form.key === 'label') {
            form.required = true
            if (value === 'hint') {
              form.required = false
            }
          }
          return form
        })
      }, () => {
@@ -240,7 +282,7 @@
    const { openType } = this.state
    let value = e.target.value
    if (key === 'resourceType') {
      let _options = this.getOptions(openType, value, this.state.supField)
      let _options = this.getOptions(openType, value, this.state.supField, this.state.display)
      
      this.setState({
        resourceType: value,
@@ -249,7 +291,27 @@
          return form
        })
      })
    } else if (key === 'display') {
      let _options = this.getOptions(openType, this.state.resourceType, this.state.supField, value)
      this.setState({
        display: value,
        formlist: this.state.formlist.map(form => {
          form.show = _options.includes(form.key)
          return form
        })
      })
    } else if (key === 'multiple') {
      if (value === 'true') {
        this.props.form.setFieldsValue({fieldlength: 512})
      } else {
        this.props.form.setFieldsValue({fieldlength: 50})
      }
    }
  }
  changeField = (data) => {
    this.setState({cFields: data})
  }
  handleSubmit = (e) => {
@@ -262,6 +324,7 @@
  getFields() {
    const { getFieldDecorator } = this.props.form
    const { openType } = this.state
    const fields = []
    this.state.formlist.forEach((item, index) => {
@@ -355,6 +418,27 @@
              </Form.Item>
            </Col>
          )
        } else if (item.key === 'width') {
          fields.push(
            <Col span={12} key={index}>
              <Form.Item label={
                <Tooltip placement="topLeft" title={item.tooltip}>
                  <Icon type="question-circle" />
                  {item.label}
                </Tooltip>
              }>
                {getFieldDecorator(item.key, {
                  initialValue: item.initVal,
                  rules: [
                    {
                      required: !!item.required,
                      message: this.props.dict['form.required.input'] + item.label + '!'
                    }
                  ]
                })(<InputNumber min={1} max={24} precision={0} />)}
              </Form.Item>
            </Col>
          )
        } else {
          fields.push(
            <Col span={12} key={index}>
@@ -409,7 +493,12 @@
      } else if (item.type === 'multiselect') { // 多选
        fields.push(
          <Col span={12} key={index}>
            <Form.Item label={item.label}>
            <Form.Item label={item.tooltip ?
              <Tooltip placement="topLeft" title={item.tooltip}>
                <Icon type="question-circle" />
                {item.label}
              </Tooltip> : item.label
            }>
              {getFieldDecorator(item.key, {
                initialValue: item.initVal
              })(
@@ -458,10 +547,10 @@
            </Form.Item>
          </Col>
        )
      } else if (item.type === 'textarea') {
      } else if (item.type === 'codemirror') {
        fields.push(
          <Col span={20} offset={4} key={index}>
            <Form.Item className="text-area">
          <Col span={24} key={index}>
            <Form.Item className="text-area" label={item.label}>
              {getFieldDecorator(item.key, {
                initialValue: item.initVal,
                rules: [
@@ -474,15 +563,52 @@
            </Form.Item>
          </Col>
        )
      } else if (item.type === 'options') {
      } else if (item.type === 'textarea') {
        fields.push(
          <Col span={20} offset={4} key={index}>
            <Form.Item className="text-area">
          <Col span={24} key={index}>
            <Form.Item className="text-msg" label={item.label}>
              {getFieldDecorator(item.key, {
                initialValue: item.initVal,
                rules: [
                  {
                    required: !!item.required,
                    message: this.props.dict['form.required.input'] + item.label + '!'
                  }
                ]
              })(<TextArea rows={4} />)}
            </Form.Item>
          </Col>
        )
      } else if (item.type === 'options') {
        if (openType !== 'checkcard') {
          fields.push(
            <Col span={24} key={index}>
              <Form.Item label={item.label} className="text-area">
                {getFieldDecorator(item.key, {
                  initialValue: item.initVal
                })(<EditTable dict={this.props.dict} type={openType} linkSubFields={this.state.linkSubFields}/>)}
              </Form.Item>
            </Col>
          )
        } else {
          fields.push(
            <Col span={24} key={index}>
              <Form.Item label={item.label} className="text-area">
                {getFieldDecorator(item.key, {
                  initialValue: item.initVal
                })(<DataTable dict={this.props.dict} type={this.state.display} fields={this.state.cFields}/>)}
              </Form.Item>
            </Col>
          )
        }
      } else if (item.type === 'fields') {
        fields.push(
          <Col span={24} key={index}>
            <Form.Item label={item.label} className="text-area">
              {getFieldDecorator(item.key, {
                initialValue: item.initVal
              })(<EditTable dict={this.props.dict} type={this.state.openType} linkSubFields={this.state.linkSubFields}/>)}
              })(<FieldsTable dict={this.props.dict} onChange={this.changeField}/>)}
            </Form.Item>
            {/* <EditTable data={item.initVal} dict={this.props.dict} type={this.state.openType} linkSubFields={this.state.linkSubFields} ref="editTable"/> */}
          </Col>
        )
      }
@@ -575,7 +701,7 @@
      }
    }
    return (
      <Form {...formItemLayout} className="ant-advanced-search-form modal-fields-form" id="modal-fields-form-box">
      <Form {...formItemLayout} className="modal-fields-form" id="modal-fields-form-box">
        <Row gutter={24}>{this.getFields()}</Row>
      </Form>
    )
src/templates/zshare/modalform/index.scss
@@ -1,22 +1,38 @@
.ant-advanced-search-form.modal-fields-form {
.modal-fields-form {
  min-height: 180px;
  .ant-col-offset-4 {
    padding-left: 6px!important;
    padding-bottom: 20px;
  }
  .ant-form-item.text-area {
    margin-bottom: 0px;
    .ant-form-item-control-wrapper {
      width: 100%;
    >.ant-form-item-control-wrapper {
      width: 84%;
      .ant-table-tbody > tr > td {
        padding: 16px 10px;
      }
    }
    >.ant-form-item-label {
      width: 16%;
    }
    .CodeMirror {
      height: 150px;
    }
  }
  .ant-form-item.text-msg {
    >.ant-form-item-label {
      width: 16%;
    }
    >.ant-form-item-control-wrapper {
      width: 84%;
    }
  }
  .ant-form-item-label .anticon-question-circle {
    color: #c49f47;
    margin-right: 3px;
  }
  .ant-radio-group {
    white-space: nowrap;
  }
  .ant-input-number {
    width: 100%;
  }
src/templates/zshare/modalform/modaleditable/index.jsx
@@ -131,39 +131,30 @@
      data = []
    }
    let _width = '40%'
    let fields = []
    let dataItem = data[0] || ''
    if (type === 'link') {
      _width = '27%'
    } else if (type === 'select') {
      _width = Math.floor(80 / (linkSubFields.length + 2)) + '%'
    if (type === 'select' || type === 'radio') {
      fields = linkSubFields.map(cell => {
        return {
          title: cell.label,
          dataIndex: cell.field,
          width: _width,
          editable: true,
          datatype: dataItem && typeof(dataItem[cell.field]) === 'number' ? 'number' : 'string'
        }
      })
    }
    let columns = [
      {
        title: 'Value',
        dataIndex: 'Value',
        width: _width,
        editable: true,
        datatype: dataItem && typeof(dataItem.Value) === 'number' ? 'number' : 'string'
      },
      {
        title: 'Text',
        dataIndex: 'Text',
        width: _width,
        editable: true,
        datatype: dataItem && typeof(dataItem.Text) === 'number' ? 'number' : 'string'
      },
@@ -171,6 +162,7 @@
      {
        title: '操作',
        align: 'center',
        width: '20%',
        dataIndex: 'operation',
        render: (text, record) =>
          this.state.dataSource.length >= 1 ? (
@@ -193,7 +185,6 @@
      columns.unshift({
        title: 'ParentID',
        dataIndex: 'ParentID',
        width: '27%',
        editable: true,
        datatype: dataItem && typeof(dataItem.ParentID) === 'number' ? 'number' : 'string'
      })
@@ -345,10 +336,9 @@
  resetColumn = (type, linkSubFields) => {
    let dataSource = JSON.parse(JSON.stringify(this.state.dataSource))
    let _width = '40%'
    let fields = []
    if (type === 'select' && linkSubFields.length > this.state.linkSubFields) {
    if ((type === 'select' || type === 'radio') && linkSubFields.length > this.state.linkSubFields) {
      let addcol = linkSubFields[linkSubFields.length - 1]
      dataSource = dataSource.map(data => {
        data[addcol.field] = data.Text
@@ -358,15 +348,11 @@
    let dataItem = dataSource ? dataSource[0] : ''
    if (type === 'link') {
      _width = '27%'
    } else if (type === 'select') {
      _width = Math.floor(80 / (linkSubFields.length + 2)) + '%'
    if (type === 'select' || type === 'radio') {
      fields = linkSubFields.map(field => {
        return {
          title: field.label,
          dataIndex: field.field,
          width: _width,
          editable: true,
          datatype: dataItem && typeof(dataItem[field.field]) === 'number' ? 'number' : 'string'
        }
@@ -377,14 +363,12 @@
      {
        title: 'Value',
        dataIndex: 'Value',
        width: _width,
        editable: true,
        datatype: dataItem && typeof(dataItem.Value) === 'number' ? 'number' : 'string'
      },
      {
        title: 'Text',
        dataIndex: 'Text',
        width: _width,
        editable: true,
        datatype: dataItem && typeof(dataItem.Text) === 'number' ? 'number' : 'string'
      },
@@ -392,6 +376,7 @@
      {
        title: '操作',
        align: 'center',
        width: '20%',
        dataIndex: 'operation',
        render: (text, record) =>
          this.state.dataSource.length >= 1 ? (
@@ -414,7 +399,6 @@
      columns.unshift({
        title: 'ParentID',
        dataIndex: 'ParentID',
        width: '27%',
        editable: true,
        datatype: dataItem && typeof(dataItem.ParentID) === 'number' ? 'number' : 'string'
      })
src/templates/zshare/modalform/modaleditable/index.scss
@@ -2,7 +2,7 @@
  .add-row {
    position: absolute;
    z-index: 1;
    right: 20px;
    right: 10px;
    top: -30px;
    padding: 5px;
    font-size: 18px;
@@ -40,4 +40,9 @@
    margin-right: 10px;
    cursor: pointer;
  }
  .ant-form-explain {
    .editable-row {
      font-size: 12px;
    }
  }
}