king
2025-05-13 1779677cece5864b62a65df4b01a4a69496e149a
src/tabviews/zshare/settingcomponent/editTable/index.jsx
@@ -1,48 +1,47 @@
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import { fromJS } from 'immutable'
import { Table, Form, Icon, Select, Cascader, notification, message } from 'antd'
import { Table, Form, Select, Cascader } from 'antd'
import { EditOutlined } from '@ant-design/icons'
import zhCN from '@/locales/zh-CN/model.js'
import enUS from '@/locales/en-US/model.js'
import './index.scss'
let eTDict = localStorage.getItem('lang') !== 'en-US' ? zhCN : enUS
const EditableContext = React.createContext()
const shortkeycode = {
  65: 'A', 66: 'B', 67: 'C', 68: 'D', 69: 'E', 70: 'F', 71: 'G', 72: 'H', 73: 'I', 74: 'J', 75: 'K', 76: 'L', 77: 'M',
  78: 'N', 79: 'O', 80: 'P', 81: 'Q', 82: 'R', 83: 'S', 84: 'T', 85: 'U', 86: 'V', 87: 'W', 88: 'X', 89: 'Y', 90: 'Z'
}
class EditableCell extends Component {
class CustomEditableCell extends Component {
  getInput = () => {
    const { inputType, options } = this.props
    const { inputType, options, record } = this.props
    if (inputType === 'select') {
      let _options = []
      if (record.$port) {
        _options = window.GLOB.UserCacheMap.get(record.$port) || []
      }
      return (
        <Select>
          {options.map((item, i) => (<Select.Option key={i} value={item.value}> {item.text} </Select.Option>))}
        <Select allowClear>
          {_options.map((item, i) => (<Select.Option key={i} title={item.value} value={item.value}> {item.text} </Select.Option>))}
        </Select>
      )
    } else if (inputType === 'cascader') {
      return (
        <Cascader options={options} placeholder=""/>
        <Cascader allowClear options={options} placeholder=""/>
      )
    }
  }
  renderCell = (form) => {
    const { getFieldDecorator } = form
    const { editing, dataIndex, title, record, children, className, required, inputType } = this.props
    const { editing, editable, dataIndex, record, children, className } = this.props
    return (
      <td className={className}>
        {editing ? (
        {editing && editable ? (
          <Form.Item style={{ margin: 0 }}>
            {getFieldDecorator(dataIndex, {
              rules: [
                {
                  required: required,
                  message: ['number', 'text', 'input'].includes(inputType) ? `${eTDict['form.required.input']} ${title}!` : `${eTDict['form.required.select']} ${title}!`,
                }
              ],
              initialValue: record[dataIndex],
              initialValue: record[dataIndex] || '',
            })(this.getInput())}
          </Form.Item>
        ) : (
@@ -57,10 +56,9 @@
  }
}
class EditTable extends Component {
class CustomEditTable extends Component {
  static propTpyes = {
    data: PropTypes.any,            // 数据列表
    columns: PropTypes.array,       // 显示列
    onChange: PropTypes.func        // 数据变化
  }
@@ -68,18 +66,33 @@
    data: [],
    editingKey: '',
    visible: false,
    columns: []
  }
  UNSAFE_componentWillMount () {
    const { data } = this.props
    let columns = fromJS(this.props.columns).toJS()
    columns.push({
      title: '操作',
    columns: [{
      title: window.GLOB.dict['name'] || '名称',
      dataIndex: 'label',
      width: '25%'
    }, {
      title: window.GLOB.dict['shortcut'] || '快捷键',
      dataIndex: 'shortcut',
      inputType: 'cascader',
      editable: true,
      options: [],
      width: '25%',
      render: (text) => {
        if (!text) return ''
        return text[0] + '+' + shortkeycode[text[1]]
      }
    }, {
      title: window.GLOB.dict['printer'] || '打印机',
      dataIndex: 'printer',
      inputType: 'select',
      editable: true,
      options: [],
      width: '25%'
    }, {
      title: window.GLOB.dict['operation'] || '操作',
      dataIndex: 'operation',
      width: '140px',
      render: (text, record) => {
      render: (_, record) => {
        const { editingKey } = this.state
        const editable = this.isEditing(record)
        return editable ? (
@@ -87,23 +100,93 @@
            <EditableContext.Consumer>
              {form => (
                <span onClick={() => this.save(form, record.uuid)} style={{ marginRight: 8 , color: '#1890ff', cursor: 'pointer'}}>
                  {eTDict['model.save']}
                  {window.GLOB.dict['save'] || '保存'}
                </span>
              )}
            </EditableContext.Consumer>
            <span style={{ color: '#1890ff', cursor: 'pointer'}} onClick={() => this.cancel(record.uuid)}>{eTDict['model.cancel']}</span>
            <span style={{ color: '#1890ff', cursor: 'pointer'}} onClick={() => this.cancel(record.uuid)}>{window.GLOB.dict['cancel'] || '取消'}</span>
          </div>
        ) : (
          <div className={'edit-operation-btn' + (editingKey !== '' ? ' disabled' : '')} style={{minWidth: '110px'}}>
            <span className="primary" onClick={() => {editingKey === '' && this.edit(record.uuid)}}><Icon type="edit" /></span>
            <span className="primary" onClick={() => {editingKey === '' && this.edit(record.uuid)}}><EditOutlined /></span>
          </div>
        )
      }
    }],
    printTypeColumns: [
      {
        title: window.GLOB.dict['print_type'] || '打印类型',
        dataIndex: 'Text',
        width: '26.1%'
      },
      {
        title: window.GLOB.dict['printer'] || '打印机',
        dataIndex: 'printer',
        inputType: 'select',
        editable: true,
        options: [],
      },
      {
        title: window.GLOB.dict['operation'] || '操作',
        dataIndex: 'operation',
        width: '153px',
        render: (_, record) => {
          const { editingKey } = this.state
          const editable = this.isEditing(record)
          return editable ? (
            <div style={{textAlign: 'center', minWidth: '110px'}}>
              <EditableContext.Consumer>
                {form => (
                  <span onClick={() => this.save(form, record.uuid, record.parentId)} style={{ marginRight: 8 , color: '#1890ff', cursor: 'pointer'}}>
                    {window.GLOB.dict['save'] || '保存'}
                  </span>
                )}
              </EditableContext.Consumer>
              <span style={{ color: '#1890ff', cursor: 'pointer'}} onClick={() => this.cancel(record.uuid)}>{window.GLOB.dict['cancel'] || '取消'}</span>
            </div>
          ) : (
            <div className={'edit-operation-btn' + (editingKey !== '' ? ' disabled' : '')} style={{minWidth: '110px'}}>
              <span className="primary" onClick={() => {editingKey === '' && this.edit(record.uuid)}}><EditOutlined /></span>
            </div>
          )
        }
      }
    ]
  }
  UNSAFE_componentWillMount () {
    const { data } = this.props
    let keys = ['shift', 'ctrl', 'alt']
    let _options = []
    keys.forEach(item => {
      let _op = {
        value: item,
        label: item,
        children: []
      }
      Object.keys(shortkeycode).forEach(key => {
        if (item === 'ctrl' && ['65', '67', '68', '69', '70', '71', '72', '74', '75', '76', '78', '79', '80', '82', '83', '84', '85', '86', '87', '88', '90'].includes(key)) return
        if (item === 'alt' && ['65', '68', '69', '70'].includes(key)) return
        _op.children.push({
          value: +key,
          label: shortkeycode[key]
        })
      })
      _options.push(_op)
    })
    this.setState({
      data: data || [],
      columns
      data: data,
      columns: this.state.columns.map(item => {
        if (item.dataIndex === 'shortcut') {
          item.options = _options
        }
        return item
      })
    })
  }
@@ -111,81 +194,6 @@
  cancel = () => {
    this.setState({ editingKey: '' })
  }
  copy = (item) => {
    const { type } = this.props
    const { data } = this.state
    if (!data || data.length === 0) {
      message.warning('未获取到配置信息')
      return
    }
    let msg = { key: type }
    if (item) {
      msg.type = 'line'
      msg.data = item
    } else {
      msg.type = 'array'
      msg.data = data
    }
    try {
      msg = window.btoa(window.encodeURIComponent(JSON.stringify(msg)))
    } catch {
      console.warn('Stringify Failure')
      msg = ''
    }
    if (msg) {
      let oInput = document.createElement('input')
      oInput.value = msg
      document.body.appendChild(oInput)
      oInput.select()
      document.execCommand('Copy')
      document.body.removeChild(oInput)
      message.success('复制成功。')
    }
  }
  onSave = (record) => {
    const { columns } = this.state
    const newData = [...this.state.data]
    const index = newData.findIndex(item => record.uuid === item.uuid)
    if (index === -1) {
      notification.warning({
        top: 92,
        message: '数据错误,无法找到行ID!',
        duration: 5
      })
      return
    }
    let unique = true
    columns.forEach(col => {
      if (col.unique !== true || !unique) return
      let _index = newData.findIndex(item => record.uuid !== item.uuid && record[col.dataIndex] === item[col.dataIndex])
      if (_index > -1) {
        notification.warning({
          top: 92,
          message: col.title + '不可重复!',
          duration: 5
        })
        unique = false
      }
    })
    if (!unique) return
    newData.splice(index, 1, record)
    this.setState({ data: newData, editingKey: '' }, () => {
      this.props.onChange(newData)
    })
  }
  handleDelete = (uuid) => {
@@ -199,48 +207,38 @@
    })
  }
  save(form, uuid) {
    const { columns } = this.state
  save(form, uuid, parentId) {
    form.validateFields((error, row) => {
      if (error) {
        return;
      }
      const newData = [...this.state.data]
      const index = newData.findIndex(item => uuid === item.uuid)
      let unique = true
      columns.forEach(col => {
        if (col.unique !== true || !unique) return
      let newData = null
        let _index = newData.findIndex(item => uuid !== item.uuid && row[col.dataIndex] === item[col.dataIndex])
        if (_index > -1) {
          notification.warning({
            top: 92,
            message: col.title + '不可重复!',
            duration: 5
          })
          unique = false
        }
      })
      if (!unique) return
      if (index > -1) {
        const item = newData[index]
        newData.splice(index, 1, {
          ...item,
          ...row,
        })
        this.setState({ data: newData, editingKey: '' }, () => {
          this.props.onChange(newData)
      if (parentId) {
        newData = this.state.data.map(item => {
          if (parentId === item.uuid) {
            item.verify.printerTypeList = item.verify.printerTypeList.map(cell => {
              if (uuid === cell.uuid) {
                cell = {...cell, ...row}
              }
              return cell
            })
          }
          return item
        })
      } else {
        newData.push(row);
        this.setState({ data: newData, editingKey: '' }, () => {
          this.props.onChange(newData)
        newData = this.state.data.map(item => {
          if (uuid === item.uuid) {
            item = {...item, ...row}
          }
          return item
        })
      }
      this.setState({ data: newData, editingKey: '' }, () => {
        this.props.onChange(newData)
      })
    })
  }
@@ -248,25 +246,10 @@
    this.setState({ editingKey: uuid })
  }
  moveRow = (dragIndex, hoverIndex) => {
    const { editingKey } = this.state
    let _data = fromJS(this.state.data).toJS()
    if (editingKey) return
    _data.splice(hoverIndex, 0, ..._data.splice(dragIndex, 1))
    this.setState({
      data: _data
    }, () => {
      this.props.onChange(_data)
    })
  }
  render() {
    let components = {
      body: {
        cell: EditableCell
        cell: CustomEditableCell
      }
    }
    
@@ -279,30 +262,53 @@
          inputType: col.inputType,
          dataIndex: col.dataIndex,
          options: col.options || [],
          required: col.required !== false ? true : false,
          title: col.title,
          editable: col.dataIndex === 'shortcut' || record.funcType === 'print',
          editing: this.isEditing(record),
          onSave: this.onSave,
        }),
      }
    })
    const printTypeColumns = this.state.printTypeColumns.map(col => {
      if (!col.editable) return col
      return {
        ...col,
        onCell: record => ({
          record,
          inputType: col.inputType,
          dataIndex: col.dataIndex,
          options: [],
          title: col.title,
          editable: true,
          editing: this.isEditing(record),
        }),
      }
    })
    return (
      <EditableContext.Provider value={this.props.form}>
        <div className="modal-edit-table">
        <div className="modal-custom-edit-table">
          <Table
            bordered
            rowKey="uuid"
            components={components}
            dataSource={this.state.data}
            columns={columns}
            rowClassName="editable-row"
            rowClassName={(record) => 'editable-row' + (record.$expanded ? ' print' : '')}
            pagination={false}
            onRow={(record, index) => ({
              index,
              moveAble: !this.state.editingKey,
              moveRow: this.moveRow,
            })}
            expandedRowRender={record => (
              record.$expanded ?
                <Table
                  bordered
                  rowKey="key"
                  size="small"
                  components={components}
                  rowClassName="editable-row"
                  dataSource={record.verify.printerTypeList}
                  columns={printTypeColumns}
                  pagination={false}
                /> : null
            )}
          />
        </div>
      </EditableContext.Provider>
@@ -310,4 +316,4 @@
  }
}
export default Form.create()(EditTable)
export default Form.create()(CustomEditTable)