king
2024-08-25 326aa6b3effaccc71cfe0775d47b0f29eb3695a6
src/templates/sharecomponent/actioncomponent/verifyexcelout/index.jsx
@@ -1,15 +1,15 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import { fromJS } from 'immutable'
import { Form, Tabs, Row, Col, Button, notification, Modal, message, InputNumber, Spin, Typography, Popconfirm } from 'antd'
import { Form, Tabs, Row, Col, Button, Input, notification, Modal, message, InputNumber, Spin, Typography, Popconfirm } from 'antd'
import { EditOutlined, StopOutlined, CheckCircleOutlined, SwapOutlined, DeleteOutlined } from '@ant-design/icons'
import moment from 'moment'
import md5 from 'md5'
import Api from '@/api'
import Utils from '@/utils/utils.js'
import SettingUtils from './utils.jsx'
import ColumnForm from './columnform'
import OtherForm from './otherform'
import DataSource from './datasource'
import CustomScript from './customscript'
import asyncComponent from '@/utils/asyncComponent'
@@ -17,6 +17,7 @@
const { TabPane } = Tabs
const { confirm } = Modal
const { Search } = Input
const { Paragraph } = Typography
const EditTable = asyncComponent(() => import('@/templates/zshare/editTable'))
@@ -30,6 +31,9 @@
    verify: {},
    debugId: '',
    activeKey: 'setting',
    visible: false,
    line: null,
    searchKey: '',
    excelColumns: [
      {
        title: '字段',
@@ -37,6 +41,8 @@
        inputType: 'input',
        editable: true,
        unique: true,
        searchable: true,
        copy: true,
        width: '16%'
      },
      {
@@ -44,6 +50,7 @@
        dataIndex: 'Text',
        inputType: 'input',
        editable: true,
        searchable: true,
        unique: true,
        width: '16%'
      },
@@ -63,7 +70,8 @@
        inputType: 'select',
        editable: true,
        required: false,
        width: '12%',
        keyCol: true,
        width: '10%',
        render: (text) => {
          if (text === 'image') {
            return '图片'
@@ -80,41 +88,12 @@
        ]
      },
      {
        title: '取绝对值',
        dataIndex: 'abs',
        inputType: 'radio',
        editable: true,
        required: false,
        width: '12%',
        render: (text) => {
          if (text === 'true') {
            return '是'
          } else {
            return '否'
          }
        },
        options: [
          {value: 'true', text: '是'},
          {value: 'false', text: '否'}
        ]
      },
      {
        title: '小数位',
        dataIndex: 'decimal',
        inputType: 'number',
        min: 0,
        max: 18,
        editable: true,
        required: false,
        width: '12%'
      },
      {
        title: '导出',
        dataIndex: 'output',
        inputType: 'radio',
        editable: true,
        required: false,
        width: '12%',
        width: '10%',
        render: (text) => {
          if (text !== 'false') {
            return '是'
@@ -138,6 +117,123 @@
          {value: 'true', text: '是'},
          {value: 'false', text: '否'}
        ]
      },
      // {
      //   title: '取绝对值',
      //   dataIndex: 'abs',
      //   inputType: 'radio',
      //   editable: true,
      //   required: false,
      //   keyVals: ['number'],
      //   width: '10%',
      //   render: (text, record) => {
      //     if (record.type !== 'number') return ''
      //     if (text === 'true') {
      //       return '是'
      //     } else {
      //       return '否'
      //     }
      //   },
      //   options: [
      //     {value: 'true', text: '是'},
      //     {value: 'false', text: '否'}
      //   ]
      // },
      // {
      //   title: '0值导出',
      //   dataIndex: 'noValue',
      //   inputType: 'radio',
      //   editable: true,
      //   required: false,
      //   keyVals: ['number'],
      //   width: '10%',
      //   render: (text, record) => {
      //     if (record.type !== 'number') return ''
      //     if (text !== 'false') {
      //       return '是'
      //     } else {
      //       return '否'
      //     }
      //   },
      //   options: [
      //     {value: 'true', text: '是'},
      //     {value: 'false', text: '否'}
      //   ]
      // },
      {
        title: '小数位',
        dataIndex: 'decimal',
        inputType: 'number',
        min: 0,
        max: 18,
        editable: true,
        required: false,
        keyVals: ['number'],
        width: '12%',
        render: (text, record) => record.type === 'number' ? text : ''
      },
      {
        title: '其他',
        dataIndex: 'other',
        required: false,
        width: '18%',
        render: (_, record) => {
          if (record.type === 'number') {
            let val = ''
            if (record.abs === 'true') {
              val += '取绝对值;'
            }
            if (record.noValue === 'false') {
              val += '0值不导出;'
            }
            if (record.format) {
              if (record.format === 'thdSeparator') {
                val += '格式化:千分位;'
              } else if (record.format === 'thdSepPm') {
                val += '格式化:千分位(负值红色);'
              } else if (record.format === 'percent') {
                val += '格式化:百分比;'
              }
            }
            if (record.prefix) {
              val += `前缀:${record.prefix};`
            }
            if (record.postfix) {
              val += `后缀:${record.postfix};`
            }
            return <div>{val}<EditOutlined className="edit-other" onClick={() => {this.setState({visible: true, line: fromJS(record).toJS()})}} /></div>
          } else if (record.type === 'text') {
            let val = ''
            if (record.wrapText === 'true') {
              val += '自动换行;'
            }
            if (record.noValue === 'false') {
              val += '空值不导出;'
            }
            if (record.textFormat) {
              if (record.textFormat === 'YYYY-MM-DD') {
                val += '格式化:YYYY-MM-DD;'
              } else if (record.textFormat === 'YYYY-MM-DD HH:mm:ss') {
                val += '格式化:YYYY-MM-DD HH:mm:ss;'
              }
            }
            if (record.prefix) {
              val += `前缀:${record.prefix};`
            }
            if (record.postfix) {
              val += `后缀:${record.postfix};`
            }
            return <div>{val}<EditOutlined className="edit-other" onClick={() => {this.setState({visible: true, line: fromJS(record).toJS()})}} /></div>
          }
          return ''
        }
      },
    ],
    scriptsColumns: [
@@ -195,12 +291,12 @@
        dataIndex: 'operation',
        render: (text, record) =>
          (<div style={{textAlign: 'center'}}>
            <span className="operation-btn" title="编辑" onClick={() => this.handleEdit(record, 'scripts')} style={{color: '#1890ff'}}><EditOutlined /></span>
            <span className="operation-btn" title="状态切换" onClick={() => this.handleStatus(record, 'scripts')} style={{color: '#8E44AD'}}><SwapOutlined /></span>
            <span className="operation-btn" title="编辑" onClick={() => this.handleEdit(record)} style={{color: '#1890ff'}}><EditOutlined /></span>
            <span className="operation-btn" title="状态切换" onClick={() => this.handleStatus(record)} style={{color: '#8E44AD'}}><SwapOutlined /></span>
            <Popconfirm
              overlayClassName="popover-confirm"
              title="确定删除吗?"
              onConfirm={() => this.handleDelete(record, 'scripts')
              onConfirm={() => this.handleDelete(record)
            }>
              <span className="operation-btn" style={{color: '#ff4d4f'}}><DeleteOutlined /></span>
            </Popconfirm>
@@ -225,6 +321,7 @@
      col.type = col.type || 'text'
      col.output = col.output || 'true'
      col.required = col.required || 'false'
      col.noValue = col.noValue || 'true'
      if (!['text', 'image', 'number'].includes(col.type)) {
        if (/^Decimal/ig.test(col.type)) {
@@ -232,6 +329,13 @@
        } else {
          col.type = 'text'
        }
      }
      if (col.type !== 'number') {
        col.decimal = ''
        col.abs = 'false'
      } else {
        col.abs = col.abs || 'false'
      }
      return col
@@ -345,20 +449,16 @@
    }
    this.setState({
      searchKey: '',
      verify: _verify,
      searches: searches,
      activeKey: card.intertype === 'system' && _verify.dataType === 'custom' ? 'setting' : 'columns'
    })
  }
  handleEdit = (record, type) => {
    let node = null
    if (type === 'scripts') {
      this.scriptsForm.edit(record)
      node = document.getElementById('mk-exout-script')
    }
  handleEdit = (record) => {
    this.scriptsForm.edit(record)
    let node = document.getElementById('mk-exout-script')
    if (node && node.scrollTop) {
      let inter = Math.ceil(node.scrollTop / 10)
@@ -374,26 +474,24 @@
    }
  }
  handleStatus = (record, type) => {
  handleStatus = (record) => {
    let verify = JSON.parse(JSON.stringify(this.state.verify))
    record.status = record.status === 'false' ? 'true' : 'false'
    if (type === 'scripts') {
      verify.scripts = verify.scripts.map(item => {
        if (item.uuid === record.uuid) {
          return record
        } else {
          return item
        }
      })
    }
    verify.scripts = verify.scripts.map(item => {
      if (item.uuid === record.uuid) {
        return record
      } else {
        return item
      }
    })
    this.setState({
      verify: verify
    })
  }
  columnChange = (values) => {
  columnChange = (values, callback) => {
    let verify = JSON.parse(JSON.stringify(this.state.verify))
    let fields = verify.columns.map(item => item.Column)
@@ -404,6 +502,8 @@
        duration: 5
      })
      return
    } else {
      callback()
    }
    values.uuid = Utils.getuuid()
    values.abs = 'false'
@@ -416,38 +516,12 @@
    })
  }
  handleDelete = (record, type) => {
    const { verify } = this.state
  handleDelete = (record) => {
    let verify = JSON.parse(JSON.stringify(this.state.verify))
    verify.columns = verify.columns.filter(item => item.uuid !== record.uuid)
    verify.scripts = verify.scripts.filter(item => item.uuid !== record.uuid)
    this.setState({ verify: verify })
  }
  handleUpDown = (record, type, direction) => {
    let verify = JSON.parse(JSON.stringify(this.state.verify))
    let index = 0
    verify.columns = verify.columns.filter((item, i) => {
      if (item.uuid === record.uuid) {
        index = i
      }
      return item.uuid !== record.uuid
    })
    if ((index === 0 && direction === 'up') || (index === verify.columns.length && direction === 'down')) {
      return
    }
    if (direction === 'up') {
      verify.columns.splice(index - 1, 0, record)
    } else {
      verify.columns.splice(index + 1, 0, record)
    }
    this.setState({
      verify: verify
    })
  }
  showError = (errorType) => {
@@ -492,6 +566,7 @@
  }
  handleConfirm = () => {
    const { card, config } = this.props
    const { activeKey, verify } = this.state
    
    // 表单提交时检查输入值是否正确
@@ -507,6 +582,51 @@
        })
        
        return
      }
      if (verify.dataType === 'custom') {
        if (this.scriptsForm && this.scriptsForm.props.form.getFieldValue('sql') && !/^\s+$/.test(this.scriptsForm.props.form.getFieldValue('sql'))) {
          notification.warning({
            top: 92,
            message: '存在未保存脚本,请点击确定保存,或点击取消放弃修改!',
            duration: 5
          })
          this.setState({activeKey: 'scripts'})
          return
        }
      }
      if (this.columnRef && this.columnRef.state.editingKey) {
        notification.warning({
          top: 92,
          message: '字段未保存!',
          duration: 5
        })
        return
      }
      if (card.intertype === 'system' && verify.dataType !== 'custom' && verify.columns.length > 0 && config.$c_ds && config.setting.interType === 'system' && config.columns && config.columns.length > 0) {
        let cols = []
        let columns = config.columns.map(c => c.field)
        if (config.subtype === 'dualdatacard' && config.subColumns) {
          config.subColumns.forEach(item => {
            columns.push(item.field)
          })
        }
        verify.columns.forEach(col => {
          if (col.output === 'false' || col.Column === '$Index') return
          if (!columns.includes(col.Column)) {
            cols.push(col.Column)
          }
        })
        if (cols.length) {
          notification.warning({
            top: 92,
            message: `导出列(${cols.join('、')})在字段集中不存在!`,
            duration: 5
          })
        }
      }
      if (activeKey === 'setting') {
@@ -537,19 +657,10 @@
                loading: false
              })
              reject()
            }, verify.scripts)
            }, verify.scripts, 'submit')
          })
        })
      } else if (activeKey === 'columns') {
        if (this.columnRef && this.columnRef.state.editingKey) {
          notification.warning({
            top: 92,
            message: '字段未保存!',
            duration: 5
          })
          return
        }
        if (this.props.card.intertype !== 'system' || verify.dataType !== 'custom') {
          resolve(verify)
        } else {
@@ -565,18 +676,9 @@
              loading: false
            })
            reject()
          }, verify.scripts)
          }, verify.scripts, 'submit')
        }
      } else if (activeKey === 'scripts') {
        if (this.scriptsForm && this.scriptsForm.props.form.getFieldValue('sql') && !/^\s+$/.test(this.scriptsForm.props.form.getFieldValue('sql'))) {
          notification.warning({
            top: 92,
            message: '存在未保存脚本,请点击确定保存,或点击取消放弃修改!',
            duration: 5
          })
          return
        }
        this.setState({loading: true})
        this.sqlverify(() => { // 验证成功
          this.setState({
@@ -588,7 +690,7 @@
            loading: false
          })
          reject()
        }, verify.scripts)
        }, verify.scripts, 'submit')
      } else {
        resolve(verify)
      }
@@ -600,11 +702,25 @@
    const { verify } = this.state
    let columns = fromJS(verify.columns).toJS()
    let fields = columns.map(item => item.Column)
    let _names = {}
    let fields = columns.map(item => {
      let key = item.Column.toLowerCase()
      _names[key] = item.Text
      return key
    })
    let names = {$up: false}
    config.columns.forEach(item => {
      if (fields.includes(item.field) || !item.field) return
      fields.push(item.field)
      if (!item.field) return
      let key = item.field.toLowerCase()
      if (fields.includes(key)) {
        if (_names[key] !== item.label) {
          names.$up = true
          names[key] = item.label
        }
        return
      }
      let cell = {
        Column: item.field,
@@ -627,8 +743,15 @@
    if (config.subtype === 'dualdatacard') {
      config.subColumns.forEach(item => {
        if (fields.includes(item.field) || !item.field) return
        fields.push(item.field)
        if (!item.field) return
        let key = item.field.toLowerCase()
        if (fields.includes(key)) {
          if (_names[key] !== item.label) {
            names.$up = true
            names[key] = item.label
          }
          return
        }
  
        let cell = {
          Column: item.field,
@@ -650,19 +773,49 @@
      })
    }
    this.setState({
      verify: {...verify, columns: columns}
    })
    if (names.$up) {
      const that = this
      confirm({
        content: '部分字段名称与显示列不一致,是否更新?',
        okText: '更新',
        cancelText: '不更新',
        onOk() {
          columns = columns.map(item => {
            let key = item.Column.toLowerCase()
            if (names[key]) {
              item.Text = names[key]
            }
            return item
          })
          that.setState({
            verify: {...verify, columns: columns}
          })
        },
        onCancel() {
          that.setState({
            verify: {...verify, columns: columns}
          })
        }
      })
    } else {
      this.setState({
        verify: {...verify, columns: columns}
      })
    }
  }
  clearField = () => {
    const { verify } = this.state
    const _this = this
    const that = this
    confirm({
      content: `确定清空Excel列吗?`,
      onOk() {
        _this.setState({
        that.setState({
          verify: {
            ...verify,
            columns: []
@@ -680,6 +833,8 @@
      col.type = col.type || 'text'
      col.output = col.output || 'true'
      col.required = col.required || 'false'
      col.noValue = col.noValue || 'true'
      col.Width = col.Width || 20
      if (!['text', 'image', 'number'].includes(col.type)) {
        if (/^Decimal/ig.test(col.type)) {
@@ -688,27 +843,30 @@
          col.type = 'text'
        }
      }
      if (col.type === 'text' && col.format) {
        delete col.format
      } else if (col.type === 'number' && col.textFormat) {
        delete col.textFormat
      }
      return col
    })
    // if (columns[0] && !['image', 'text', 'number'].includes(columns[0].type)) {
    //   columns = columns.map(col => {
    //     let _cell = {
    //       uuid: Utils.getuuid(),
    //       Column: col.Column,
    //       Text: col.Text,
    //       Width: 20,
    //       abs: 'false',
    //       output: col.output || 'true',
    //       required: col.required || 'false',
    //       type: 'text',
    //     }
    //     return _cell
    //   })
    // }
    this.setState({verify: {...verify, columns}})
  }
  lineSubmit = () => {
    const { line, verify } = this.state
    let columns = verify.columns.map(col => {
      if (col.uuid === line.uuid) {
        return line
      }
      return col
    })
    this.setState({verify: {...verify, columns}, line: null, visible: false})
  }
  // 标签切换
@@ -716,28 +874,32 @@
    const { card } = this.props
    const { activeKey, verify } = this.state
    if (card.intertype !== 'system' || verify.dataType !== 'custom') {
    if (activeKey === 'setting') {
      this.settingForm.handleConfirm().then(res => {
        if (card.intertype !== 'system' || verify.dataType !== 'custom') {
          this.setState({activeKey: val, verify: {...verify, ...res}})
        } else {
          this.setState({
            verify: {...verify, ...res}
          }, () => {
            this.setState({loading: true})
            this.sqlverify(() => { // 验证成功
              this.setState({
                activeKey: val,
                loading: false
              })
            }, () => {             // 验证失败
              this.setState({
                activeKey: val,
                loading: false
              })
            }, verify.scripts)
          })
        }
      })
    } else if (card.intertype !== 'system' || verify.dataType !== 'custom') {
      this.setState({activeKey: val})
      return
    } else if (activeKey === 'setting') {
      this.settingForm.handleConfirm().then(res => {
        this.setState({
          verify: {...verify, ...res}
        }, () => {
          this.setState({loading: true})
          this.sqlverify(() => { // 验证成功
            this.setState({
              activeKey: val,
              loading: false
            })
          }, () => {             // 验证失败
            this.setState({
              activeKey: val,
              loading: false
            })
          }, verify.scripts)
        })
      })
    } else if (activeKey === 'columns') {
      if (this.columnRef && this.columnRef.state.editingKey) {
        notification.warning({
@@ -828,7 +990,7 @@
    }
  }
  sqlverify = (_resolve, _reject, scripts) => {
  sqlverify = (_resolve, _reject, scripts, type) => {
    const { searches, verify, debugId } = this.state
    if (verify.dataType !== 'custom') {
@@ -836,8 +998,7 @@
      return
    }
    let timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
    let sql = SettingUtils.getDebugSql(verify, scripts, (verify.useSearch === 'true' ? searches : []), Utils, '2023-04-20 15:29:37')
    let sql = SettingUtils.getDebugSql(verify, scripts, (verify.useSearch === 'true' ? searches : []))
    let _debugId = md5(sql)
@@ -846,24 +1007,29 @@
      return
    }
    let param = {
      func: 's_debug_sql',
      exec_type: 'y',
      LText: sql
    }
    param.LText = Utils.formatOptions(param.LText)
    param.timestamp = timestamp
    param.secretkey = Utils.encrypt('', timestamp)
    Api.genericInterface(param).then(result => {
      if (result.status) {
    Api.sDebug(sql).then(result => {
      if (result.status || result.ErrCode === '-2') {
        this.setState({debugId: _debugId})
        _resolve()
      } else {
        _reject()
        Modal.error({
          title: result.message
        })
        if (type === 'submit') {
          Modal.confirm({
            title: result.message,
            okText: '知道了',
            cancelText: '强制保存',
            onOk: () => {
              _reject()
            },
            onCancel() {
              _resolve()
            }
          })
        } else {
          _reject()
          Modal.error({
            title: result.message
          })
        }
      }
    })
  }
@@ -889,7 +1055,7 @@
  render() {
    const { card } = this.props
    const { verify, excelColumns, scriptsColumns, activeKey, loading, searches } = this.state
    const { verify, excelColumns, scriptsColumns, activeKey, loading, searches, searchKey, visible, line } = this.state
    const formItemLayout = {
      labelCol: {
        xs: { span: 24 },
@@ -917,13 +1083,13 @@
          } key="columns">
            <ColumnForm columnChange={this.columnChange}/>
            <Button className="excel-col-add mk-green" title="添加显示列字段" onClick={this.columnFieldInput}>
              同步显示列
              同步字段集
            </Button>
            <Button className="excel-col-add mk-red" title="清空Excel列" onClick={this.clearField}>
              清空Excel列
            </Button>
            <div style={{color: '#959595', fontSize: '13px', paddingLeft: '10px'}}>如需导出序号,请使用字段 $Index;数值类型导出时可进行数据处理(取绝对值、保留小数位);红色标题导出时列头文字为红色。</div>
            <EditTable actions={['edit', 'move', 'copy', 'del']} type="excelcolumn" wrappedComponentRef={(inst) => this.columnRef = inst} data={verify.columns} columns={excelColumns} onChange={this.changeColumns}/>
            <div style={{color: '#959595', fontSize: '13px', paddingLeft: '10px'}}>如需导出序号,请使用字段 $Index;导出为否时,不使用行信息(文本为空,数值为0);红色标题导出时列头文字为红色。</div>
            <EditTable actions={['edit', 'move', 'copy', 'del']} type="excelcolumn" searchKey={searchKey} wrappedComponentRef={(inst) => this.columnRef = inst} data={verify.columns} columns={excelColumns} onChange={this.changeColumns}/>
          </TabPane>
          {card.intertype === 'system' ? <TabPane tab={
            <span>
@@ -940,7 +1106,12 @@
            />
            <EditTable actions={['move']} data={verify.scripts} columns={scriptsColumns} onChange={(scripts) => {this.setState({verify: {...verify, scripts}})}}/>
          </TabPane> : null}
          <TabPane tab="信息提示" key="message">
          <TabPane tab={
            <span>
              信息提示
              {activeKey === 'columns' ? <span onClick={(e) => {e.stopPropagation()}}><Search className="mk-search-fields" defaultValue={searchKey} allowClear onSearch={(val, e) => {e.stopPropagation();this.setState({searchKey: val})}} /></span> : null}
            </span>
          } key="message">
            <Form {...formItemLayout}>
              <Row gutter={24}>
                <Col offset={6} span={6}>
@@ -1036,6 +1207,18 @@
            </Form>
          </TabPane>
        </Tabs>
        <Modal
          title=""
          visible={visible}
          width={1000}
          maskClosable={false}
          closable={false}
          onOk={this.lineSubmit}
          onCancel={() => {this.setState({visible: false, line: null})}}
          destroyOnClose
        >
          <OtherForm line={line} submit={this.lineSubmit} onChange={(values) => this.setState({line: values})}/>
        </Modal>
      </div>
    )
  }