king
2024-08-20 58826d6f4eab9f8c9acf9fa8696f60039c645cfe
src/menu/datasource/index.jsx
@@ -1,12 +1,12 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import {connect} from 'react-redux'
import { is, fromJS } from 'immutable'
import { Icon, Modal } from 'antd'
import { Modal, Button, notification } from 'antd'
import { SettingOutlined } from '@ant-design/icons'
import zhCN from '@/locales/zh-CN/model.js'
import enUS from '@/locales/en-US/model.js'
import VerifyCard from './verifycard'
import CreateFunc from '@/templates/zshare/createfunc'
import MKEmitter from '@/utils/events.js'
import './index.scss'
class DataSource extends Component {
@@ -16,18 +16,12 @@
  }
  state = {
    dict: localStorage.getItem('lang') !== 'en-US' ? zhCN : enUS,
    appType: sessionStorage.getItem('appType'),
    sourcelist: [],
    mainSearch: [],
    visible: false,
    loading: false,
    setting: null
  }
  UNSAFE_componentWillMount () {
    const { config } = this.props
    this.setState({setting: fromJS(config.setting).toJS()})
    this.props.updateConfig(config) // 触发菜单信息更新
    record: {}
  }
  shouldComponentUpdate (nextProps, nextState) {
@@ -35,8 +29,109 @@
  }
  editDataSource = () => {
    const { config } = this.props
    const { appType } = this.state
    let search = []
    let menu = fromJS(window.GLOB.customMenu).toJS()
    if (appType === 'mob') {
      let ms = null
      menu.components.forEach(item => {
        if (item.type === 'topbar' && item.wrap.type !== 'navbar' && item.search) {
          ms = item.search
        } else if (item.type === 'search' && item.wrap.field) {
          search.push({
            type: 'text',
            label: item.wrap.label,
            field: item.wrap.field,
            match: item.wrap.match,
            required: item.wrap.required,
            value: item.wrap.initval || ''
          })
        }
      })
      if (ms) {
        if (ms.setting.type === 'search') {
          search.push({
            type: 'text',
            label: '搜索栏',
            field: ms.setting.field,
            match: ms.setting.match,
            required: ms.setting.required,
            value: ms.setting.initval || ''
          })
        }
        ms.fields.forEach(item => {
          if (item.type === 'range') {
            item.initval = `${item.minValue},${item.maxValue}`
          }
          search.push(item)
        })
        ms.groups.forEach(group => {
          if (group.setting.type === 'search') {
            search.push({
              type: 'text',
              label: group.wrap.name,
              field: group.setting.field,
              match: group.setting.match,
              required: group.setting.required,
              value: group.setting.initval || ''
            })
          }
          group.fields.forEach(item => {
            if (item.type === 'range') {
              item.initval = `${item.minValue},${item.maxValue}`
            }
            search.push(item)
          })
        })
      }
    } else if (config.type === 'interface') {
      menu.components.forEach(item => {
        if (item.type !== 'search') return
        search = item.search
      })
    } else {
      let filterComponent = (box, mainSearch) => {
        box.components.forEach(item => {
          if (item.type !== 'search') return
          mainSearch = item.search
        })
        let has = false
        box.components.forEach(item => {
          if (item.uuid === config.uuid) {
            has = true
          } else if (item.type === 'group') {
            item.components.forEach(m => {
              if (m.uuid !== config.uuid) return
              has = true
            })
          }
        })
        if (has) {
          search = mainSearch || []
        } else {
          box.components.forEach(item => {
            if (item.type !== 'tabs') return
            item.subtabs.forEach(tab => {
              filterComponent(tab, mainSearch)
            })
          })
        }
      }
      filterComponent(menu, null)
    }
    this.setState({
      visible: true
      visible: true,
      mainSearch: search,
      record: {...config.setting}
    })
  }
@@ -46,37 +141,261 @@
    this.setState({loading: true})
    this.verifyRef.submitDataSource().then(res => {
      let MenuType = sessionStorage.getItem('MenuType')
      if (MenuType === 'billPrint') {
        res.setting.supModule = ['empty']
      }
      if (!res.setting.primaryKey && res.columns && res.columns.length > 0) {
        res.columns.forEach(col => {
          if (col.field.toLowerCase() === 'id') {
            res.setting.primaryKey = col.field
          }
        })
      }
      if (res.columns) {
        res.columns = res.columns.map(item => {
          if (/int/ig.test(item.datatype)) {
            item.type = 'number'
            item.decimal = 0
          } else if (/Decimal/ig.test(item.datatype)) {
            item.type = 'number'
            item.decimal = +item.datatype.replace(/^Decimal\(18,/ig, '').replace(/\)/ig, '')
          } else if (/^date/ig.test(item.datatype)) {
            item.type = 'text'
            item.fieldlength = 50
          } else {
            item.type = 'text'
            item.fieldlength = +item.datatype.replace(/^Nvarchar\(/ig, '').replace(/\)/ig, '')
          }
          return item
        })
        if (!config.fixedCol) {
          res.columns.reverse()
        }
      }
      let maxScript = 0
      let useExec = false
      let sFields = []
      res.searches && res.searches.forEach(item => {
        if (!item.key) return
        if (item.type === 'date') {
          if (sFields.includes(item.key)) {
            sFields.push(item.key + '1')
          } else {
            sFields.push(item.key)
          }
        } else if (item.type === 'dateweek' || item.type === 'range' || (item.type === 'datemonth' && item.match !== '=')) {
          sFields.push(item.key)
          sFields.push(item.key + '1')
        } else if (item.type === 'daterange') {
          if (/,/.test(item.key)) {
            sFields.push(item.key.split(',')[0])
            sFields.push(item.key.split(',')[1])
          } else {
            sFields.push(item.key)
            sFields.push(item.key + '1')
          }
        } else if (item.type === 'text' || item.type === 'select') {
          item.key.split(',').forEach(field => {
            sFields.push(field)
          })
        } else {
          sFields.push(item.key)
        }
      })
      delete res.searches
      sFields = sFields.join('|')
      // if (window.GLOB.funcs && window.GLOB.funcs.length > 0) {
      //   window.GLOB.funcs.forEach(m => {
      //     let reg = new RegExp('\\$ex@' + m.func_code + '@ex\\$', 'ig')
      //     if (res.setting.dataresource) {
      //       res.setting.dataresource = res.setting.dataresource.replace(reg, `/*$ex@${m.func_code}-begin*/\n${m.key_sql}\n/*@ex$-end*/`)
      //     }
      //     res.scripts.forEach(item => {
      //       item.sql = item.sql.replace(reg, `/*$ex@${m.func_code}-begin*/\n${m.key_sql}\n/*@ex$-end*/`)
      //       if (item.status === 'false') return
      //       if (/exec\s/ig.test(item.sql)) {
      //         useExec = true
      //         maxScript = 1000
      //       } else if (item.sql.length > maxScript) {
      //         maxScript = item.sql.length
      //       }
      //     })
      //   })
      // } else {
      //   res.scripts.forEach(item => {
      //     if (item.status === 'false') return
      //     if (/exec\s/ig.test(item.sql)) {
      //       useExec = true
      //       maxScript = 1000
      //     } else if (item.sql.length > maxScript) {
      //       maxScript = item.sql.length
      //     }
      //   })
      // }
      if (res.setting.interType === 'system' && res.setting.dataresource && res.setting.execute !== 'false' && sFields) {
        if (new RegExp(`@(${sFields})@`, 'ig').test(res.setting.dataresource)) {
          maxScript = 1000
        }
      }
      res.scripts.forEach(item => {
        if (item.status === 'false') return
        if (/exec\s/ig.test(item.sql)) {
          useExec = true
          maxScript = 1000
        } else if (sFields && new RegExp(`@(${sFields})@`, 'ig').test(item.sql)) {
          maxScript = 1000
        } else if (item.sql.length > maxScript) {
          maxScript = item.sql.length
        }
      })
      res.setting.maxScript = maxScript
      if (useExec && res.setting.sync === 'true') {
        notification.warning({
          top: 92,
          message: '当前数据源使用了同步查询且自定义脚本中存在函数exec,如遇接口报错需关闭同步查询后重新测试。',
          duration: 5
        })
      }
      if (config.subtype !== 'dualdatacard') {
        delete res.subColumns
        if (config.type === 'interface') {
          res.setting.laypage = 'false'
        }
      } else {
        res.subColumns = res.subColumns.map(item => {
          if (/int/ig.test(item.datatype)) {
            item.type = 'number'
            item.decimal = 0
          } else if (/Decimal/ig.test(item.datatype)) {
            item.type = 'number'
            item.decimal = +item.datatype.replace(/^Decimal\(18,/ig, '').replace(/\)/ig, '')
          } else if (/^date/ig.test(item.datatype)) {
            item.type = 'text'
            item.fieldlength = 50
          } else {
            item.type = 'text'
            item.fieldlength = +item.datatype.replace(/^Nvarchar\(/ig, '').replace(/\)/ig, '')
          }
          return item
        })
        res.subColumns.reverse()
      }
      if (this.verifyRef.state.debugId) {
        res.setting.debugId = this.verifyRef.state.debugId
      } else {
        delete res.setting.debugId
      }
      if (res.setting.interType === 'system' && res.setting.sync === 'true') {
        res.scripts && res.scripts.forEach(script => {
          if (script.status === 'false' || script.position !== 'back') return
          res.setting.sync = 'false'
        })
      }
      this.setState({loading: false, visible: false})
      if (res.cols) {
        res.cols = [...config.cols, ...res.cols]
      } else {
        delete res.cols
      }
      this.props.updateConfig({...config, ...res})
      if (res.setting && res.setting.tableName && config.setting && !config.setting.tableName) {
        setTimeout(() => {
          MKEmitter.emit('publicTableChange', res.setting.tableName, 'init')
        }, 100)
      }
      if ((config.type === 'card' && config.subtype === 'datacard') || (config.type === 'table' && config.subtype === 'normaltable')) {
        setTimeout(() => {
          MKEmitter.emit('mkUpdateInter', {uuid: config.uuid, columns: res.columns}, {delay: 0})
        }, 150)
      }
    }, () => {
      this.setState({loading: false})
    })
  }
  cancel = () => {
    this.verifyRef.closeDataSource(() => {
      this.setState({ visible: false, loading: false })
    })
  }
  creatFunc = () => {
    const { config } = this.props
    const { mainSearch } = this.state
    const menu = window.GLOB.customMenu
    return new Promise((resolve) => {
      this.verifyRef.submitDataSource().then(res => {
        let _config = fromJS(config).toJS()
        _config.MenuName = menu.MenuName + '-' + _config.name
        _config.menuNo = menu.MenuNo
        _config.MenuID = menu.MenuID
        _config.setting = res.setting
        _config.columns = res.columns
        _config.func = res.setting.innerFunc
        _config.$type = 'table'
        if (res.setting.useMSearch === 'true') { // 使用主搜索条件
          _config.search = [..._config.search, ...mainSearch]
        }
        resolve(_config)
      })
    })
  }
  render () {
    const { config, menu } = this.props
    const { visible, dict, loading } = this.state
    const { config } = this.props
    const { visible, loading, mainSearch, record } = this.state
    return (
      <div className="model-datasource">
        <Icon type="setting" onClick={() => this.editDataSource()} />
        <SettingOutlined title="数据源" onClick={() => this.editDataSource()} />
        <Modal
          wrapClassName="model-datasource-verify-modal popview-modal"
          title={'数据源配置'}
          wrapClassName="mk-pop-modal"
          title=""
          visible={visible}
          width={'75vw'}
          maskClosable={false}
          style={{minWidth: '900px', maxWidth: '1200px'}}
          okText={dict['model.submit']}
          onOk={this.verifySubmit}
          confirmLoading={loading}
          onCancel={() => { this.setState({ visible: false }) }}
          okText="提交"
          onCancel={() => {this.setState({ visible: false, loading: false }) }}
          footer={[
            config.subtype !== 'dualdatacard' && record.interType === 'inner' ? <CreateFunc key="create" getMsg={this.creatFunc}/> : null,
            <Button key="cancel" onClick={this.cancel}>取消</Button>,
            <Button key="confirm" type="primary" loading={loading} onClick={this.verifySubmit}>确定</Button>
          ]}
          destroyOnClose
        >
          <VerifyCard
            dict={dict}
            menu={menu}
            mainSearch={mainSearch}
            config={config}
            updRecord={(record) => this.setState({record: record})}
            wrappedComponentRef={(inst) => this.verifyRef = inst}
          />
        </Modal>
@@ -85,14 +404,4 @@
  }
}
const mapStateToProps = (state) => {
  return {
    menu: state.customMenu
  }
}
const mapDispatchToProps = () => {
  return {}
}
export default connect(mapStateToProps, mapDispatchToProps)(DataSource)
export default DataSource