From ab262bbe2c64ba086a14f181e5a27eba4b46b555 Mon Sep 17 00:00:00 2001
From: king <18310653075@163.com>
Date: 星期五, 13 十月 2023 17:59:53 +0800
Subject: [PATCH] 2023-10-13

---
 src/templates/zshare/modalform/modaleditable/index.jsx |  519 ++++++++++++++++++++++++++++++---------------------------
 1 files changed, 276 insertions(+), 243 deletions(-)

diff --git a/src/templates/zshare/modalform/modaleditable/index.jsx b/src/templates/zshare/modalform/modaleditable/index.jsx
index b8ca161..0427a95 100644
--- a/src/templates/zshare/modalform/modaleditable/index.jsx
+++ b/src/templates/zshare/modalform/modaleditable/index.jsx
@@ -1,106 +1,138 @@
 import React, {Component} from 'react'
 import PropTypes from 'prop-types'
 import { is, fromJS } from 'immutable'
-import { Table, Input, Popconfirm, Form, message } from 'antd'
-import { ArrowUpOutlined, ArrowDownOutlined, DeleteOutlined, PlusOutlined, SwapOutlined } from '@ant-design/icons'
+import { DndProvider, DragSource, DropTarget } from 'react-dnd'
+import { Table, Input, Popconfirm, message } from 'antd'
+import { DeleteOutlined, PlusOutlined, SwapOutlined, DragOutlined } from '@ant-design/icons'
 
 import Utils from '@/utils/utils.js'
+import asyncComponent from '@/utils/asyncComponent'
 import './index.scss'
 
-const EditableContext = React.createContext()
+const SourceComponent = asyncComponent(() => import('@/menu/components/share/sourcecomponent'))
 
-const EditableRow = ({ form, index, ...props }) => (
-  <EditableContext.Provider value={form}>
-    <tr {...props} />
-  </EditableContext.Provider>
+class MoveTd extends React.Component {
+  render() {
+    const { connectDragSource, connectDropTarget } = this.props
+
+    return connectDragSource(
+      connectDropTarget(<td className="mk-move-col"><DragOutlined /></td>),
+    )
+  }
+}
+
+const rowSource = {
+  beginDrag(props) {
+    return {
+      index: props.index,
+    }
+  }
+}
+
+const rowTarget = {
+  drop(props, monitor) {
+    const dragIndex = monitor.getItem().index
+    const hoverIndex = props.index
+
+    if (dragIndex === hoverIndex) {
+      return
+    }
+
+    props.moveRow(dragIndex, hoverIndex)
+
+    monitor.getItem().index = hoverIndex
+  },
+}
+
+const DragableTd = DropTarget('td', rowTarget, connect => ({
+  connectDropTarget: connect.dropTarget(),
+}))(
+  DragSource('td', rowSource, (connect, monitor) => ({
+    connectDragSource: connect.dragSource(),
+    // isDragging: monitor.isDragging()
+  }))(MoveTd),
 )
-
-const EditableFormRow = Form.create()(EditableRow)
 
 class EditableCell extends Component {
   state = {
-    editing: false
+    editing: false,
+    value: ''
   }
 
-  toggleEdit = () => {
-    const editing = !this.state.editing
-    this.setState({ editing }, () => {
-      if (editing && this.input && this.input.select) {
+  trigger = () => {
+    const { dataIndex, record } = this.props
+
+    this.setState({ editing: true, value: record[dataIndex] }, () => {
+      if (this.input && this.input.select) {
         this.input.select()
-      } else if (editing && this.input && this.input.focus) {
+      } else if (this.input && this.input.focus) {
         this.input.focus()
       }
     })
   }
 
-  save = e => {
-    const { record, handleSave } = this.props
-    this.form.validateFields((error, values) => {
-      handleSave({ ...record, ...values })
-      if (error && error[e.currentTarget.id]) {
-        return
-      }
-      this.toggleEdit()
-    })
+  save = () => {
+    const { record, handleSave, dataIndex } = this.props
+    const { value } = this.state
+
+    handleSave({ ...record, [dataIndex]: value })
+
+    this.setState({ editing: false, value: '' })
   }
 
-  renderCell = form => {
-    this.form = form
-    const { children, dataIndex, record } = this.props
+  changeUrl = (val) => {
+    const { record, handleSave, dataIndex } = this.props
+
+    handleSave({ ...record, [dataIndex]: val })
+  }
+
+  renderCell = () => {
+    const { dataIndex, inputType, record } = this.props
     const { editing } = this.state
 
-    return editing ? (
-      <Form.Item style={{ margin: '0 -5px 0 -5px' }}>
-        {form.getFieldDecorator(dataIndex, {
-          rules: [
-            {
-              required: dataIndex === 'Text',
-              message: '涓嶅彲涓虹┖.',
-            }
-          ],
-          initialValue: record[dataIndex]
-        })(<Input ref={node => (this.input = node)} autoComplete="off" onPressEnter={this.save} onBlur={this.save} />)}
-      </Form.Item>
-    ) : (
-      <div
-        className="editable-cell-value-wrap"
-        onClick={this.toggleEdit}
-      >
-        {children}
-      </div>
-    )
+    if (inputType === 'file') {
+      return <SourceComponent initialValue={record[dataIndex]} type="" onChange={this.changeUrl} placement="right"/>
+    }
+
+    if (!editing) {
+      return (
+        <div
+          className="editable-cell-value-wrap"
+          onClick={this.trigger}
+        >
+          {record[dataIndex]}
+        </div>
+      )
+    } else {
+      return <Input ref={node => (this.input = node)} defaultValue={record[dataIndex]} autoComplete="off" onChange={(e) => this.setState({value: e.target.value})} onPressEnter={this.save} onBlur={this.save} />
+    }
   }
 
   render() {
-    const {
-      editable,
-      dataIndex,
-      title,
-      record,
-      index,
-      handleSave,
-      children,
-      ...restProps
-    } = this.props
+    const { editable, dataIndex, index } = this.props
+
+    if (dataIndex === '$move') {
+      return (<DragableTd key={index} {...this.props} />)
+    }
+
+    if (editable) {
+      return (
+        <td>{this.renderCell()}</td>
+      )
+    }
+
     return (
-      <td {...restProps}>
-        {editable ? (
-          <EditableContext.Consumer style={{padding: 0}}>{this.renderCell}</EditableContext.Consumer>
-        ) : (
-          children
-        )}
-      </td>
+      <td {...this.props}/>
     )
   }
 }
 
 class EditTable extends Component {
   static propTpyes = {
-    type: PropTypes.string,         // 琛ㄥ崟绫诲瀷
-    module: PropTypes.string,       // 鍏冪礌绫诲瀷
-    linkSubFields: PropTypes.array, // 鍏宠仈瀛楁
-    transfield: PropTypes.object,   // 琛ㄥ崟瀛楁鍚嶇О
-    onChange: PropTypes.func        // 鏁版嵁鍙樺寲
+    type: PropTypes.any,
+    module: PropTypes.string,
+    columns: PropTypes.array,
+    onChange: PropTypes.func
   }
 
   state = {
@@ -110,38 +142,40 @@
   }
 
   UNSAFE_componentWillMount () {
-    const { linkSubFields, type } = this.props
-    let data = this.props['data-__meta'].initialValue || []
-
-    const { columns } = this.getColumns(type, linkSubFields, data)
+    const { columns, value } = this.props
+    let data = value || []
 
     this.setState({
-      columns: columns,
-      dataSource: data,
+      columns: this.getColumns(),
+      dataSource: data.map(item => {
+        columns.forEach(n => {
+          if (item[n.key] !== undefined) return
+          item[n.key] = ['ParentID', '$url', '$color', '$value'].includes(n.key) ? '' : item.Text || ''
+        })
+        return item
+      }),
       count: data.length
     })
   }
 
-  handleUpDown = (record, direction) => {
+  moveRow = (dragId, hoverId) => {
     const { dataSource } = this.state
-    let index = 0
-
-    let _data = dataSource.filter((item, i) => {
-      if (item.key === record.key) {
-        index = i
+    let dragIndex = -1
+    let hoverIndex = -1
+    
+    dataSource.forEach((item, i) => {
+      if (item.key === dragId) {
+        dragIndex = i
+      } else if (item.key === hoverId) {
+        hoverIndex = i
       }
-
-      return item.key !== record.key
     })
-    if ((index === 0 && direction === 'up') || (index === dataSource.length - 1 && direction === 'down')) {
-      return
-    }
+    
+    if (dragIndex === -1 || hoverIndex === -1) return
 
-    if (direction === 'up') {
-      _data.splice(index - 1, 0, record)
-    } else {
-      _data.splice(index + 1, 0, record)
-    }
+    let _data = fromJS(dataSource).toJS()
+
+    _data.splice(hoverIndex, 0, ..._data.splice(dragIndex, 1))
 
     this.setState({
       dataSource: _data
@@ -150,13 +184,14 @@
     })
   }
 
-  handleHide = (record) => {
+  handleHide = (key) => {
     let _data = this.state.dataSource.map(item => {
-      if (item.key === record.key) {
+      if (item.key === key) {
         item.Hide = !item.Hide
       }
       return item
     })
+
     this.setState({
       dataSource: _data
     }, () => {
@@ -164,7 +199,7 @@
     })
   }
 
-  handleDelete = key => {
+  handleDelete = (key) => {
     const { dataSource } = this.state
     let _data = dataSource.filter(item => item.key !== key)
 
@@ -173,22 +208,26 @@
     })
   }
 
-  handleAdd = (e) => {
-    e.stopPropagation()
-    const { linkSubFields } = this.props
+  handleAdd = () => {
+    const { columns } = this.props
     const { count, dataSource } = this.state
-    const newData = {
-      key: Utils.getuuid(),
-      Value: `${count}`,
-      Text: `${count}`,
-      ParentID: ''
-    }
 
-    linkSubFields.forEach(m => {
-      newData[m] = newData[m] || ''
+    let item = { key: Utils.getuuid() }
+
+    columns.forEach(m => {
+      item[m.key] = ''
     })
 
-    let _data = [...dataSource, newData]
+    if (item.Value === '') {
+      item.Value = `${count + 1}`
+    }
+    if (item.$value === '') {
+      item.$value = `${count + 1}`
+    }
+
+    item.Text = `${count + 1}`
+
+    let _data = [...dataSource, item]
 
     this.setState({
       dataSource: _data,
@@ -199,18 +238,49 @@
   }
 
   handleSave = row => {
-    const { type } = this.props
+    const { columns, type } = this.props
     const newData = [...this.state.dataSource]
     const index = newData.findIndex(item => row.key === item.key)
     const item = newData[index]
 
-    if (type === 'link') {
-      if (newData.filter(m => row.key !== m.key && row.Value === m.Value && row.ParentID === m.ParentID).length > 0) {
-        message.warning('鐩稿悓ParentID涓嬶紝姝alue鍊煎凡瀛樺湪锛�')
-      }
+    if (type === 'proc') {
+      // if (!row.origin || /^\s+$/.test(row.origin)) {
+      //   message.warning(columns[0].title + '涓虹┖鏃舵棤鏁堬紒')
+      // }
     } else {
-      if (newData.filter(m => row.key !== m.key && row.Value === m.Value).length > 0) {
-        message.warning('姝alue鍊煎凡瀛樺湪锛�')
+      let val = ''
+      let repeat = false
+      let _type = ''
+      columns.forEach(col => {
+        if (!col.strict) return
+  
+        if (col.key === 'ParentID') {
+          _type = 'mutil'
+        }
+  
+        val += row[col.key]
+      })
+  
+      newData.forEach(item => {
+        if (row.key === item.key) return
+  
+        let _val = ''
+        columns.forEach(col => {
+          if (!col.strict) return
+  
+          _val += item[col.key]
+        })
+  
+        if (val === _val) {
+          repeat = true
+        }
+      })
+      if (repeat) {
+        if (_type === 'mutil') {
+          message.warning('鐩稿悓ParentID涓嬶紝姝alue鍊煎凡瀛樺湪锛�')
+        } else {
+          message.warning('姝alue鍊煎凡瀛樺湪锛�')
+        }
       }
     }
 
@@ -223,112 +293,83 @@
     })
   }
 
-  getColumns = (type, linkSubFields, dataSource) => {
-    const { transfield } = this.props
+  getColumns = () => {
+    const { columns } = this.props
 
-    let _dataSource = fromJS(dataSource).toJS()
-    let fields = []
-    let subFields = linkSubFields.filter(m => m !== 'Value' && m !== 'Text')
-
-    if (subFields.length > 0) {
-      _dataSource = _dataSource.map(data => {
-        subFields.forEach(n => {
-          if (data[n] !== undefined) return
-          data[n] = data.Text || ''
-        })
-        return data
+    let fields = [{
+      title: ' ',
+      width: '60px',
+      dataIndex: '$move',
+      onCell: (record) => ({
+        index: record.key,
+        dataIndex: '$move',
+        moveRow: this.moveRow
       })
-
-      fields = subFields.map(field => {
-        return {
-          title: transfield[field] || field,
-          $title: transfield[field] || field,
-          dataIndex: field,
+    }]
+    columns.forEach(n => {
+      let col = {
+        title: n.title,
+        dataIndex: n.key,
+        onCell: record => ({
+          record,
           editable: true,
-        }
-      })
-    }
-
-    let columns = [
-      {
-        title: 'Value',
-        $title: 'Value',
-        dataIndex: 'Value',
-        editable: true
-      },
-      {
-        title: 'Text',
-        $title: 'Text',
-        dataIndex: 'Text',
-        editable: true
-      },
-      ...fields,
-      {
-        title: '鎿嶄綔',
-        align: 'center',
-        width: '20%',
-        dataIndex: 'operation',
-        render: (text, record) =>
-          this.state.dataSource.length >= 1 ? (
-            <div style={{fontSize: '15px'}}>
-              <span className="operation-btn" onClick={() => this.handleUpDown(record, 'up')} style={{color: '#1890ff'}}><ArrowUpOutlined /></span>
-              <span className="operation-btn" onClick={() => this.handleUpDown(record, 'down')} style={{color: '#ff4d4f'}}><ArrowDownOutlined /></span>
-              <span className="operation-btn" title="鏄剧ず/闅愯棌" onClick={() => this.handleHide(record)} style={{color: 'rgb(142, 68, 173)'}}><SwapOutlined /></span>
-              <Popconfirm
-                title="纭畾鍒犻櫎鍚楋紵"
-                overlayClassName="popover-confirm"
-                onConfirm={() => this.handleDelete(record.key)
-              }>
-                <span style={{color: '#ff4d4f', cursor: 'pointer'}}><DeleteOutlined /></span>
-              </Popconfirm>
-            </div>
-          ) : null,
+          inputType: n.type || 'text',
+          dataIndex: n.key,
+          handleSave: this.handleSave
+        })
       }
-    ]
 
-    if (type === 'link') {
-      columns.unshift({
-        title: 'ParentID',
-        $title: 'ParentID',
-        dataIndex: 'ParentID',
-        editable: true
-      })
-    }
+      if (n.width) {
+        col.width = n.width
+      }
+      if (n.fixed) {
+        delete col.onCell
+      }
 
-    return {
-      columns: columns.map(col => {
-        if (col.dataIndex !== 'operation') {
-          col.title = <div>
-            {col.$title}
+      fields.push(col)
+    })
+
+    fields.push({
+      title: '鎿嶄綔',
+      align: 'center',
+      width: '110px',
+      dataIndex: 'operation',
+      render: (text, record) =>
+        (
+          <div style={{fontSize: '15px'}}>
+            <span className="operation-btn" title="鏄剧ず/闅愯棌" onClick={() => this.handleHide(record.key)} style={{color: 'rgb(142, 68, 173)'}}><SwapOutlined /></span>
+            <Popconfirm
+              title="纭畾鍒犻櫎鍚楋紵"
+              overlayClassName="popover-confirm"
+              onConfirm={() => this.handleDelete(record.key)
+            }>
+              <span style={{color: '#ff4d4f', cursor: 'pointer'}}><DeleteOutlined /></span>
+            </Popconfirm>
           </div>
-        }
-        return col
-      }),
-      dataSource: _dataSource
-    }
+        )
+    })
+
+    return fields
   }
 
-  handleEmpty = (e) => {
-    e.stopPropagation()
-    const { linkSubFields, module } = this.props
+  handleEmpty = () => {
+    const { columns, module } = this.props
     const { dataSource } = this.state
 
     if (dataSource.filter(item => item.Value === '').length > 0) {
       message.warning('Value涓虹┖宸插瓨鍦紒')
       return
     }
-    const newData = {
-      key: Utils.getuuid(),
-      Value: '',
-      Text: module === 'form' ? '绌�' : '鍏ㄩ儴',
-      ParentID: ''
-    }
 
-    linkSubFields.forEach(m => {
-      newData[m] = newData[m] || ''
+    let item = { key: Utils.getuuid() }
+
+    columns.forEach(m => {
+      item[m.key] = ''
     })
 
-    let _data = [newData, ...dataSource]
+    item.Text = module === 'form' ? '绌�' : '鍏ㄩ儴'
+
+    let _data = [item, ...dataSource]
 
     this.setState({
       dataSource: _data,
@@ -337,65 +378,57 @@
     })
   }
 
-  resetColumn = (type, linkSubFields) => {
-    const { columns, dataSource } = this.getColumns(type, linkSubFields, this.state.dataSource)
+  resetColumn = () => {
+    const { columns, value } = this.props
+    
+    let data = fromJS(value).toJS().map(item => {
+      columns.forEach(n => {
+        if (item[n.key] !== undefined) return
+        item[n.key] = ['ParentID', '$url', '$color', '$value'].includes(n.key) ? '' : item.Text || ''
+      })
+      return item
+    })
 
-    if (!is(fromJS(dataSource), fromJS(this.state.dataSource))) {
-      this.setState({
-        columns,
-        dataSource
-      }, () => {
-        this.props.onChange(dataSource)
-      })
-    } else {
-      this.setState({
-        columns
-      })
-    }
+    this.setState({
+      columns: this.getColumns(),
+      dataSource: data,
+      count: data.length
+    }, () => {
+      this.props.onChange(data)
+    })
   }
 
   UNSAFE_componentWillReceiveProps (nextProps) {
-    if (!is(fromJS(this.props.linkSubFields), fromJS(nextProps.linkSubFields)) || this.props.type !== nextProps.type) {
-      this.resetColumn(nextProps.type, nextProps.linkSubFields)
+    if (!is(fromJS(this.props.columns), fromJS(nextProps.columns))) {
+      this.setState({}, () => {
+        this.resetColumn()
+      })
     }
   }
 
   render() {
     const { module } = this.props
-    const { dataSource } = this.state
+    const { dataSource, columns } = this.state
     const components = {
       body: {
-        row: EditableFormRow,
         cell: EditableCell
       }
     }
-    const columns = this.state.columns.map(col => {
-      if (!col.editable) {
-        return col
-      }
-      return {
-        ...col,
-        onCell: record => ({
-          record,
-          editable: col.editable,
-          dataIndex: col.dataIndex,
-          title: col.title,
-          handleSave: this.handleSave
-        })
-      }
-    })
+
     return (
       <div className="common-modal-edit-table">
-        <span className="add-row add-row-empty" onClick={this.handleEmpty}>{module === 'form' ? '绌�' : '鍏ㄩ儴'}</span>
+        {module ? <span className="add-row add-row-empty" onClick={this.handleEmpty}>{module === 'form' ? '绌�' : '鍏ㄩ儴'}</span> : null}
         <PlusOutlined className="add-row" onClick={this.handleAdd} />
-        <Table
-          components={components}
-          rowClassName={(record) => record.Hide ? 'editable-row hide' : 'editable-row'}
-          bordered
-          dataSource={dataSource}
-          columns={columns}
-          pagination={false}
-        />
+        <DndProvider>
+          <Table
+            components={components}
+            rowClassName={(record) => record.Hide ? 'editable-row hide' : 'editable-row'}
+            bordered
+            dataSource={dataSource}
+            columns={columns}
+            pagination={false}
+          />
+        </DndProvider>
       </div>
     )
   }

--
Gitblit v1.8.0