king
2024-03-03 67036fb0ed31d77ca33b660ce5f9f47c29ae65c0
src/menu/datasource/verifycard/customscript/index.jsx
@@ -1,26 +1,30 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import { Form, Row, Col, Button, notification, Select } from 'antd'
import { is, fromJS } from 'immutable'
import { Form, Row, Col, Button, notification, Select, Tooltip, Modal, Switch, Radio } from 'antd'
import { QuestionCircleOutlined } from '@ant-design/icons'
import Toast from 'antd-mobile/es/components/toast'
import Dialog from 'antd-mobile/es/components/dialog'
import Utils from '@/utils/utils.js'
import { checkSQL, getSearchFields } from '@/utils/utils-custom.js'
import CodeMirror from '@/templates/zshare/codemirror'
import MKEmitter from '@/utils/events.js'
import './index.scss'
class CustomForm extends Component {
  static propTpyes = {
    type: PropTypes.string,         // 菜单类型
    dict: PropTypes.object,         // 字典项
    type: PropTypes.string,         // 组件类型
    defaultsql: PropTypes.string,   // 默认sql
    setting: PropTypes.object,      // 设置
    searches: PropTypes.array,      // 搜索条件
    swhere: PropTypes.string,       // where条件
    arr_field: PropTypes.string,    // 列字段
    regoptions: PropTypes.array,    // 正则替换
    systemScripts: PropTypes.array, // 系统脚本
    scriptSubmit: PropTypes.func,   // 脚本验证后提交
    scriptsChange: PropTypes.func   // 脚本验证
    scriptsChange: PropTypes.func,
    addProcess: PropTypes.func
  }
  state = {
    skip: false,
    editItem: null,
    loading: false,
    usefulFields: ''
@@ -29,29 +33,17 @@
  UNSAFE_componentWillMount() {
    const { searches } = this.props
    let _usefulFields = []
    searches.forEach(item => {
      if (!item.field) return
      if (item.type === 'group') {
        if (item.transfer === 'true') {
          _usefulFields.push(item.field)
        }
        _usefulFields.push(item.datefield)
        _usefulFields.push(item.datefield + '1')
      } else if (['dateweek', 'datemonth', 'daterange'].includes(item.type)) {
        _usefulFields.push(item.field)
        _usefulFields.push(item.field + '1')
      } else if (_usefulFields.includes(item.field)) {
        _usefulFields.push(item.field + '1')
      } else {
        _usefulFields.push(item.field)
      }
    })
    this.setState({
      usefulFields: _usefulFields.join(', ')
      usefulFields: getSearchFields(searches)
    })
  }
  UNSAFE_componentWillReceiveProps (nextProps) {
    if (!is(fromJS(this.props.searches), fromJS(nextProps.searches))) {
      this.setState({
        usefulFields: getSearchFields(nextProps.searches)
      })
    }
  }
  edit = (record) => {
@@ -60,7 +52,8 @@
    })
    this.props.form.setFieldsValue({
      sql: record.sql
      sql: record.sql,
      position: record.position || 'front'
    })
  }
@@ -69,79 +62,97 @@
      editItem: null
    })
    this.props.form.setFieldsValue({
      sql: ''
      sql: ' ',
      position: 'front'
    })
  }
  handleConfirm = () => {
    const { skip } = this.state
    // 表单提交时检查输入值是否正确
    this.props.form.validateFieldsAndScroll((err, values) => {
      if (!err) {
        if (/^[\s\n]+$/.test(values.sql)) {
          notification.warning({
            top: 92,
            message: '请输入sql!',
            duration: 5
          })
          return
        }
        values.uuid = this.state.editItem ? this.state.editItem.uuid : ''
        let _quot = values.sql.match(/'{1}/g)
        let _lparen = values.sql.match(/\({1}/g)
        let _rparen = values.sql.match(/\){1}/g)
        let pass = checkSQL(values.sql, 'customscript')
        _quot = _quot ? _quot.length : 0
        _lparen = _lparen ? _lparen.length : 0
        _rparen = _rparen ? _rparen.length : 0
        if (!pass) return
        if (_quot % 2 !== 0) {
          notification.warning({
            top: 92,
            message: 'sql中\'必须成对出现',
            duration: 5
          })
          return
        } else if (_lparen !== _rparen) {
          notification.warning({
            top: 92,
            message: 'sql中()必须成对出现',
            duration: 5
          })
          return
        } else if (/--/ig.test(values.sql)) {
          notification.warning({
            top: 92,
            message: '自定义sql语句中,不可出现字符 -- ,注释请用 /*内容*/',
            duration: 5
          })
          return
        }
        let error = Utils.verifySql(values.sql, 'customscript')
        if (error) {
          notification.warning({
            top: 92,
            message: 'sql中不可使用' + error,
            duration: 5
          })
          return
        }
        this.setState({loading: true})
        this.props.scriptsChange(values).then(() => {
        if (skip) {
          this.setState({
            editItem: null,
            loading: false
            skip: false
          })
          if (values.uuid) {
            MKEmitter.emit('editLineId', values.uuid)
          }
          this.props.form.setFieldsValue({
            sql: ''
            sql: ' '
          })
          this.props.scriptSubmit(values)
        })
        } else {
          this.setState({loading: true})
          this.props.scriptsChange(values).then(() => {
            this.setState({
              editItem: null,
              loading: false
            })
            if (values.uuid) {
              MKEmitter.emit('editLineId', values.uuid)
            }
            this.props.form.setFieldsValue({
              sql: ' '
            })
            this.props.scriptSubmit(values)
          }, () => {
            this.setState({
              loading: false
            })
          })
        }
      }
    })
  }
  selectScript = (value, option) => {
    const { setting } = this.props
    let _sql = this.props.form.getFieldValue('sql')
    if (_sql) {
    if (_sql === ' ') {
      _sql = ''
    } else if (_sql) {
      _sql = _sql + ` 
      `
    }
    if (value === 'defaultsql') {
      value = this.props.defaultsql
    } else if (value === 'flowstart') {
      value = `/* select a.*, w.remark as remark_w, w.statusname  as statusname_w,w.status as status_w,w.works_flow_param,w.modifydate as modifydate_w  from (select * from ${setting.tableName} where status=0 and deleted=0 $@ and createuserid=@userid@ @$) a
      inner join (select * from  s_my_works_flow  where works_flow_code=@works_flow_code@ and status=0 and deleted=0) w on a.id=w.works_flow_id */`
      this.props.addProcess()
    } else if (value === 'flowcheck') {
      value = `/* select a.*, w.remark as remark_w, w.statusname  as statusname_w,w.status as status_w,w.works_flow_param,w.modifydate as modifydate_w
      from (select * from ${setting.tableName} where status=0 and deleted=0 ) a
      inner join (select * from  s_my_works_flow  where works_flow_code=@works_flow_code@ and status>0 and status<888 and deleted=0) w
      on a.id=w.works_flow_id
      $@ inner join (select works_flow_id  from s_my_works_flow_role where userid=@userid@ and  works_flow_code=@works_flow_code@ and deleted=0 ) r
      on r.works_flow_id=w.works_flow_id @$ */`
      this.props.addProcess()
    }
    _sql = _sql.replace(/\s{6}$/, '')
@@ -155,53 +166,127 @@
    })
  }
  render() {
    const { systemScripts, setting } = this.props
    const { getFieldDecorator } = this.props.form
    const { usefulFields } = this.state
    const formItemLayout = {
      labelCol: {
        xs: { span: 24 },
        sm: { span: 8 }
      },
      wrapperCol: {
        xs: { span: 24 },
        sm: { span: 16 }
  showError = (type) => {
    let appType = sessionStorage.getItem('appType')
    if (type === 'S') {
      if (appType === 'mob') {
        Toast.show({ icon: 'success', content: '执行成功!', duration: 3000 })
      } else {
        notification.success({
          top: 92,
          message: '执行成功!',
          duration: 2
        })
      }
    } else if (type === 'Y') {
      if (appType === 'mob') {
        Dialog.alert({content: '执行成功!', confirmText: '知道了'})
      } else {
        Modal.success({
          title: '执行成功!'
        })
      }
    } else if (type === 'N') {
      if (appType === 'mob') {
        Dialog.alert({content: '执行失败!', confirmText: '知道了'})
      } else {
        Modal.error({
          title: '执行失败!'
        })
      }
    } else {
      if (appType === 'mob') {
        Toast.show({ icon: 'fail', content: '执行失败!', duration: 3000 })
      } else {
        notification.error({
          top: 92,
          message: '执行失败!',
          duration: 10
        })
      }
    }
  }
  render() {
    const { systemScripts, setting, type } = this.props
    const { getFieldDecorator } = this.props.form
    const { usefulFields, skip } = this.state
    let urlFields = window.GLOB.urlFields ? window.GLOB.urlFields.join(', ') : ''
    return (
      <Form {...formItemLayout} className="modal-menu-setting-script">
      <Form className="modal-source-setting-script">
        <Row gutter={24}>
          {setting.tableName ? <Col span={8}>
            <Form.Item label={'表名'} style={{whiteSpace: 'nowrap', margin: 0}}>
          {setting.tableName ? <Col span={6}>
            <Form.Item label="表名" style={{whiteSpace: 'nowrap', margin: 0}}>
              {setting.tableName}
            </Form.Item>
          </Col> : null}
          <Col span={16}>
            <Form.Item label={'报错字段'} style={{margin: 0}}>
          <Col span={18}>
            <Form.Item label="报错字段" style={{margin: 0}}>
              ErrorCode, retmsg
              <span style={{marginLeft: 25}}>
                成功:
                <span className="error-val" onClick={() => {this.showError('S')}}> S </span>、
                <span className="error-val" onClick={() => {this.showError('Y')}}> Y </span>、
                -1(不提示)
              </span>
              <span style={{marginLeft: 20}}>
                失败:
                <span className="error-val" onClick={() => {this.showError('N')}}> N </span>、
                -2(不提示)、
                <span className="error-val" onClick={() => {this.showError('')}}> 其他 </span>
              </span>
            </Form.Item>
          </Col>
          <Col span={24} className="sqlfield">
            <Form.Item label={'可用字段'}>
              id, bid, loginuid, sessionuid, userid, appkey, time_id, calendarDate, calendarDate1{usefulFields ? ', ' + usefulFields : ''}
          <Col span={24}>
            <Form.Item label="可用字段" className="field-able">
              <Tooltip mouseLeaveDelay={0.3} mouseEnterDelay={0.3} placement="top" title={'公共值,请按照@xxx@格式使用。'}><span style={{color: '#1890ff'}}>BID, LoginUID, SessionUid, UserID, Appkey, time_id, typename, datam</span></Tooltip>,&nbsp;
              <Tooltip mouseLeaveDelay={0.3} mouseEnterDelay={0.3} placement="top" title={'系统变量,系统会定义变量并赋值。'}><span style={{color: '#fa8c16'}}>UserName, FullName, RoleID, mk_departmentcode, mk_organization, mk_user_type, mk_nation, mk_province, mk_city, mk_district, mk_address</span></Tooltip>,&nbsp;
              <Tooltip mouseLeaveDelay={0.3} mouseEnterDelay={0.3} placement="top" title={'排序、分页以及搜索条件变量,请按照@xxx@格式使用。使用@pageSize@或@orderBy@代表自定义分页,总数请以mk_total返回。'}>orderBy, pageSize, pageIndex{usefulFields ? ', ' + usefulFields : ''}{type === 'calendar' ? ', mk_year' : ''}</Tooltip>
              <Tooltip mouseLeaveDelay={0.3} mouseEnterDelay={0.3} placement="top" title={'url变量,请按照@xxx@格式使用。'}>{urlFields ? ', ' : ''}<span style={{color: '#13c2c2'}}>{urlFields}</span></Tooltip>
              {window.GLOB.process ? <Tooltip mouseLeaveDelay={0.3} mouseEnterDelay={0.3} placement="top" title={'工作流变量,请按照@xxx@格式使用。'}>, <span style={{color: 'purple'}}>works_flow_code</span></Tooltip> : null}
            </Form.Item>
          </Col>
          <Col span={10}>
            <Form.Item label={'快捷添加'} style={{marginBottom: 0}}>
          <Col span={8} style={{whiteSpace: 'nowrap'}}>
            <Form.Item style={{marginBottom: 0}} label={
              <Tooltip placement="bottomLeft" title={'自定义脚本与数据源位置关系。'}>
                <QuestionCircleOutlined className="mk-form-tip" />
                执行位置
              </Tooltip>
            }>
              {getFieldDecorator('position', {
                initialValue: 'front'
              })(
                <Radio.Group>
                  <Radio value="front">前置</Radio>
                  <Radio value="back">后置</Radio>
                </Radio.Group>
              )}
            </Form.Item>
          </Col>
          <Col span={8}>
            <Form.Item label="快捷添加" labelCol={{xs: { span: 24 }, sm: { span: 6 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 18 }} } style={{marginBottom: 0}}>
              <Select
                showSearch
                filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0}
                onChange={this.selectScript}
                onSelect={this.selectScript}
              >
                <Select.Option style={{whiteSpace: 'normal'}} key="default" value="defaultsql">默认sql</Select.Option>
                {window.GLOB.process ? <Select.Option style={{whiteSpace: 'normal'}} key="flowstart" value="flowstart">默认sql(工作流-发起)</Select.Option> : null}
                {window.GLOB.process ? <Select.Option style={{whiteSpace: 'normal'}} key="flowcheck" value="flowcheck">默认sql(工作流-审核)</Select.Option> : null}
                <Select.Option key="debugger" value={`z_debug: select @ErrorCode='E',@retmsg='测试断点' goto aaa`}>
                  测试断点
                </Select.Option>
                {systemScripts.map((option, i) =>
                  <Select.Option style={{whiteSpace: 'normal'}} key={i} value={option.value}>{option.name}</Select.Option>
                )}
              </Select>
            </Form.Item>
          </Col>
          <Col span={6} className="add">
          <Col span={5} style={{whiteSpace: 'nowrap'}}>
            <Button onClick={this.handleConfirm} loading={this.state.loading} className="mk-green" style={{marginTop: 5, marginBottom: 15, marginLeft: 30}}>
              保存
            </Button>
@@ -209,17 +294,21 @@
              取消
            </Button>
          </Col>
          <Col span={3} style={{paddingTop: '15px', fontSize: '12px', whiteSpace: 'nowrap'}}>
            强制保存:
            <Switch checked={skip} size="small" onChange={() => this.setState({skip: !skip})}/>
          </Col>
          <Col span={24} className="sql">
            <Form.Item label={'sql'}>
            <Form.Item label="sql">
              {getFieldDecorator('sql', {
                initialValue: '',
                rules: [
                  {
                    required: true,
                    message: this.props.dict['form.required.input'] + 'sql!'
                    message: '请输入sql!'
                  }
                ]
              })(<CodeMirror />)}
              })(<CodeMirror/>)}
            </Form.Item>
          </Col>
        </Row>