king
2020-07-15 b8cdbe3fbd57bbd513509a7d76c529096b1a7153
2020-07-15
9个文件已修改
1个文件已添加
740 ■■■■■ 已修改文件
src/locales/en-US/mob.js 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/locales/zh-CN/mob.js 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/mob/datasource/index.jsx 59 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/mob/datasource/index.scss 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/mob/datasource/verifycard/customscript/index.jsx 78 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/mob/datasource/verifycard/index.jsx 282 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/mob/datasource/verifycard/index.scss 118 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/mob/datasource/verifycard/settingform/index.jsx 95 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/mob/datasource/verifycard/utils.jsx 99 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/zshare/formconfig.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/locales/en-US/mob.js
@@ -5,6 +5,9 @@
  'mob.cancel': '取消',
  'mob.edit': '编辑',
  'mob.header.logout': '退出',
  'mob.status.open': '启用',
  'mob.status.change': '切换',
  'mob.status.forbidden': '禁用',
  'mob.query.delete': '确定删除吗?',
  'mob.header.logout.hint': '您确定要退出吗?',
  'mob.required.input': '请输入',
src/locales/zh-CN/mob.js
@@ -5,6 +5,9 @@
  'mob.cancel': '取消',
  'mob.edit': '编辑',
  'mob.header.logout': '退出',
  'mob.status.open': '启用',
  'mob.status.change': '切换',
  'mob.status.forbidden': '禁用',
  'mob.query.delete': '确定删除吗?',
  'mob.header.logout.hint': '您确定要退出吗?',
  'mob.required.input': '请输入',
src/mob/datasource/index.jsx
@@ -9,6 +9,8 @@
import VerifyCard from './verifycard'
import './index.scss'
const { confirm } = Modal
class DataSource extends Component {
  static propTpyes = {
    config: PropTypes.any,
@@ -20,7 +22,14 @@
    sourcelist: [],
    searches: [],
    visible: false,
    loading: false,
    source: null
  }
  UNSAFE_componentWillMount () {
    const { config } = this.props
    this.setState({sourcelist: config.sourcelist || []})
  }
  UNSAFE_componentWillReceiveProps(nextProps) {
@@ -50,19 +59,62 @@
    })
  }
  closeDataSource = () => {
  closeDataSource = (item) => {
    const { config } = this.props
    let sourcelist = fromJS(this.state.sourcelist).toJS()
    const _this = this
    sourcelist = sourcelist.filter(cell => cell.uuid !== item.uuid)
    confirm({
      title: '确定删除数据源吗?',
      content: '',
      okText: _this.state.dict['mob.confirm'],
      cancelText: _this.state.dict['mob.cancel'],
      onOk() {
        _this.setState({sourcelist})
        _this.props.updateConfig({...config, sourcelist: fromJS(sourcelist).toJS()})
      },
      onCancel() {}
    })
  }
  verifySubmit = () => {
    const { config } = this.props
    let sourcelist = fromJS(this.state.sourcelist).toJS()
    this.setState({loading: true})
    this.verifyRef.submitDataSource().then((res) => {
      let isadd = true
      sourcelist = sourcelist.map(item => {
        if (item.uuid === res.uuid) {
          isadd = false
          return res
        } else {
          return item
        }
      })
      if (isadd) {
        sourcelist.push(res)
      }
      this.setState({loading: false, visible: false, sourcelist})
      this.props.updateConfig({...config, sourcelist: fromJS(sourcelist).toJS()})
    }, () => {
      this.setState({loading: false})
    })
  }
  render () {
    const { sourcelist, visible, source, dict, searches } = this.state
    const { sourcelist, visible, source, dict, searches, loading } = this.state
    return (
      <div className="mob-datasource">
        {sourcelist.map(item => (
          <span className="mob-input-group-wrapper" key={item.uuid}>
            <span className="mob-input-wrapper">
              <span className="mob-input-value">{item.label}</span>
              <span className="mob-input-value">{item.setting.name}</span>
              <span className="mob-input-group-addon">
                <Icon type="setting" onClick={() => this.editDataSource(item)} />
                <Icon type="close" onClick={() => this.closeDataSource(item)} />
@@ -87,6 +139,7 @@
          okText={dict['mob.submit']}
          cancelText={dict['mob.cancel']}
          onOk={this.verifySubmit}
          confirmLoading={loading}
          onCancel={() => { this.setState({ visible: false }) }}
          destroyOnClose
        >
src/mob/datasource/index.scss
@@ -28,6 +28,7 @@
        text-overflow:ellipsis;
        white-space: nowrap;
        padding: 2px 10px;
        color: #ffffff;
      }
      .mob-input-group-addon {
src/mob/datasource/verifycard/customscript/index.jsx
@@ -1,11 +1,8 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import { Form, Row, Col, Input, Button, notification, Modal, Select } from 'antd'
import moment from 'moment'
import { Form, Row, Col, Input, Button, notification, Select } from 'antd'
import Utils from '@/utils/utils.js'
// import SettingUtils from '../utils.jsx'
import Api from '@/api'
import './index.scss'
const { TextArea } = Input
@@ -20,7 +17,8 @@
    arr_field: PropTypes.string,    // 列字段
    regoptions: PropTypes.array,    // 正则替换
    systemScripts: PropTypes.array, // 系统脚本
    scriptsChange: PropTypes.func   // 表单
    scriptSubmit: PropTypes.func,   // 脚本验证后提交
    scriptsChange: PropTypes.func   // 脚本验证
  }
  state = {
@@ -75,9 +73,6 @@
  }
  handleConfirm = () => {
    // const { setting, arr_field, regoptions, swhere } = this.props
    const { setting } = this.props
    // 表单提交时检查输入值是否正确
    this.props.form.validateFieldsAndScroll((err, values) => {
      if (!err) {
@@ -125,61 +120,16 @@
          return
        }
        let _customScript = ''
        setting.scripts && setting.scripts.forEach(script => {
          if (this.state.editItem && this.state.editItem.uuid === script.uuid) {
            _customScript += `
            ${values.sql}
            `
          } else if (script.status !== 'false') {
            _customScript += `
            ${script.sql}
            `
          }
        })
        if (!this.state.editItem) {
          _customScript += `
            ${values.sql}
            `
        }
        if (_customScript) {
          _customScript = `declare @ErrorCode nvarchar(50),@retmsg nvarchar(4000) select @ErrorCode='',@retmsg =''
            ${_customScript}
          `
        }
        // let _setting = {...setting, customScript: _customScript}
        let param = {
          func: 's_debug_sql',
          // LText: SettingUtils.getDebugSql(_setting, arr_field, regoptions, swhere)
        }
        param.LText = Utils.formatOptions(param.LText)
        param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss') + '.000'
        param.secretkey = Utils.encrypt(param.LText, param.timestamp)
        this.setState({loading: true})
        Api.getLocalConfig(param).then(res => {
          if (res.status) {
            this.setState({
              loading: false,
              editItem: null
            }, () => {
              this.props.scriptsChange(values)
            })
            this.props.form.setFieldsValue({
              sql: ''
            })
          } else {
            this.setState({loading: false})
            Modal.error({
              title: res.message
            })
          }
        this.props.scriptsChange(values).then(() => {
          this.setState({
            editItem: null,
            loading: false
          })
          this.props.form.setFieldsValue({
            sql: ''
          })
          this.props.scriptSubmit(values)
        })
      }
    })
@@ -234,7 +184,7 @@
          </Col>
          <Col span={24} className="sqlfield">
            <Form.Item label={'可用字段'}>
              id, bid, loginuid, sessionuid, userid, appkey, orderBy{setting.laypage !== 'false' ? ', pageSize, pageIndex': ''}{usefulFields ? ', ' + usefulFields : ''}
              id, bid, loginuid, sessionuid, userid, appkey, time_id, orderBy{setting.laypage !== 'false' ? ', pageSize, pageIndex': ''}{usefulFields ? ', ' + usefulFields : ''}
            </Form.Item>
          </Col>
          <Col span={10}>
@@ -265,7 +215,7 @@
                rules: [
                  {
                    required: true,
                    message: this.props.dict['form.required.input'] + 'sql!'
                    message: this.props.dict['mob.required.input'] + 'sql!'
                  }
                ]
              })(<TextArea rows={15} />)}
src/mob/datasource/verifycard/index.jsx
@@ -1,7 +1,7 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import { fromJS } from 'immutable'
import { Form, Tabs, Table, Popconfirm, Icon, notification, Modal, Typography } from 'antd'
import { Form, Tabs, Table, Popconfirm, Icon, notification, Modal, Typography, Spin } from 'antd'
import moment from 'moment'
import Api from '@/api'
@@ -10,10 +10,10 @@
import ColForm from './columnform'
import CustomScriptsForm from './customscript'
import SettingForm from './settingform'
import SettingUtils from './utils'
import './index.scss'
const { TabPane } = Tabs
const { confirm } = Modal
const { Paragraph } = Typography
class VerifyCard extends Component {
@@ -27,6 +27,7 @@
  state = {
    columns: [],
    activeKey: 'setting',
    loading: false,
    initsql: '',          // sql验证时变量声明及赋值
    usefulfields: '',
    defaultsql: '',         // 默认Sql
@@ -82,13 +83,13 @@
        render: (text, record) => record.status === 'false' ?
          (
            <div>
              {this.props.dict['header.form.status.forbidden']}
              {this.props.dict['mob.status.forbidden']}
              <Icon style={{marginLeft: '5px'}} type="stop" theme="twoTone" twoToneColor="#ff4d4f" />
            </div>
          ) :
          (
            <div>
              {this.props.dict['header.form.status.open']}
              {this.props.dict['mob.status.open']}
              <Icon style={{marginLeft: '5px'}} type="check-circle" theme="twoTone" twoToneColor="#52c41a" />
            </div>
          )
@@ -101,13 +102,13 @@
        render: (text, record) =>
          (<div>
            <span className="operation-btn" title={this.props.dict['model.edit']} onClick={() => this.handleEdit(record, 'scripts')} style={{color: '#1890ff'}}><Icon type="edit" /></span>
            <span className="operation-btn" title={this.props.dict['header.form.up']} onClick={() => this.handleUpDown(record, 'up')} style={{color: '#1890ff'}}><Icon type="arrow-up" /></span>
            <span className="operation-btn" title={this.props.dict['header.form.down']} onClick={() => this.handleUpDown(record, 'down')} style={{color: '#ff4d4f'}}><Icon type="arrow-down" /></span>
            <span className="operation-btn" title={this.props.dict['header.form.status.change']} onClick={() => this.handleStatus(record)} style={{color: '#8E44AD'}}><Icon type="swap" /></span>
            <span className="operation-btn" onClick={() => this.handleUpDown(record, 'up')} style={{color: '#1890ff'}}><Icon type="arrow-up" /></span>
            <span className="operation-btn" onClick={() => this.handleUpDown(record, 'down')} style={{color: '#ff4d4f'}}><Icon type="arrow-down" /></span>
            <span className="operation-btn" title={this.props.dict['mob.status.change']} onClick={() => this.handleStatus(record)} style={{color: '#8E44AD'}}><Icon type="swap" /></span>
            <Popconfirm
              title={this.props.dict['header.form.query.delete']}
              okText={this.props.dict['model.confirm']}
              cancelText={this.props.dict['header.cancel']}
              title={this.props.dict['mob.query.delete']}
              okText={this.props.dict['mob.confirm']}
              cancelText={this.props.dict['mob.cancel']}
              onConfirm={() => this.deleteScript(record)
            }>
              <span className="operation-btn" style={{color: '#ff4d4f'}}><Icon type="delete" /></span>
@@ -127,13 +128,7 @@
    })
  }
  componentDidMount() {
  }
  getsysScript = () => {
    const { defaultsql } = this.state
    let _scriptSql = `Select distinct func+Remark as funcname,longparam, s.Sort from  s_custom_script s inner join (select OpenID from sapp where ID=@Appkey@) p on s.openid = case when s.appkey='' then s.openid else p.OpenID end order by s.Sort`
    _scriptSql = Utils.formatOptions(_scriptSql)
@@ -153,13 +148,6 @@
    Api.getSystemConfig(_sParam).then(res => {
      if (res.status) {
        let _scripts = []
        if (defaultsql) {
          _scripts.push({
            name: '默认sql',
            value: defaultsql
          })
        }
        res.data.forEach(item => {
          let _item = {
@@ -201,26 +189,6 @@
    this.setState({ columns })
  }
  scriptsChange = (values) => {
    let scripts = fromJS(this.state.scripts).toJS()
    if (values.uuid) {
      scripts = scripts.map(item => {
        if (item.uuid === values.uuid) {
          return values
        } else {
          return item
        }
      })
    } else {
      values.uuid = Utils.getuuid()
      scripts.push(values)
    }
    this.setState({ scripts })
  }
  deleteColumn = (record) => {
    this.setState({ columns: this.state.columns.filter(item => item.uuid !== record.uuid) })
@@ -292,63 +260,192 @@
    this.setState({ scripts })
  }
  handleConfirm = () => {
    const { card } = this.props
    const { setting, scripts, columns } = this.state
    // 表单提交时检查输入值是否正确
  scriptsChange = (values) => {
    let scripts = fromJS(this.state.scripts).toJS()
    if (values.uuid) {
      scripts = scripts.map(item => {
        if (item.uuid === values.uuid) {
          return values
        } else {
          return item
        }
      })
    } else {
      scripts.push(values)
    }
    return new Promise((resolve, reject) => {
      if (setting.default === 'false' && scripts.length === 0) {
        notification.warning({
          top: 92,
          message: '不执行默认sql时,必须设置自定义脚本!',
          duration: 5
        })
        return
      }
      let _loading = false
      if (this.scriptsForm && this.scriptsForm.state.editItem) {
        _loading = true
      }
      if (this.scriptsForm && this.scriptsForm.props.form.getFieldValue('sql')) {
        _loading = true
      }
      if (_loading) {
        confirm({
          content: `存在未保存项,确定提交吗?`,
          okText: this.props.dict['mob.confirm'],
          cancelText: this.props.dict['mob.cancel'],
          onOk() {
            resolve({
              uuid: card.uuid,
              setting: setting,
              columns: columns,
              scripts: scripts
            })
          },
          onCancel() {}
        })
      } else {
        resolve({
          uuid: card.uuid,
          setting: setting,
          columns: columns,
          scripts: scripts
        })
      }
      this.sqlverify(resolve, reject, false, scripts)
    })
  }
  scriptSubmit = (values) => {
    let scripts = fromJS(this.state.scripts).toJS()
    if (values.uuid) {
      scripts = scripts.map(item => {
        if (item.uuid === values.uuid) {
          return values
        } else {
          return item
        }
      })
    } else {
      values.uuid = Utils.getuuid()
      scripts.push(values)
    }
    this.setState({ scripts })
  }
  changeTab = (val) => {
    const { activeKey } = this.state
    this.setState({loading: true})
    if (activeKey === 'setting') {
      this.settingForm.handleConfirm().then(res => {
        console.log(res)
        this.setState({
          setting: res
        }, () => {
          this.sqlverify(() => { // 验证成功
            this.setState({
              activeKey: val,
              loading: false
            })
          }, () => {             // 验证失败
            this.setState({
              loading: false
            })
          }, true)
        })
      }, () => {
        this.setState({loading: false})
      })
    } else if (activeKey === 'columns') {
      this.sqlverify(() => { // 验证成功
        this.setState({
          activeKey: val,
          loading: false
        })
      }, () => {             // 验证失败
        this.setState({
          loading: false
        })
      }, true)
    } else if (activeKey === 'scripts') {
      let _loading = false
      if (this.scriptsForm && this.scriptsForm.state.editItem) {
        _loading = true
      } else if (this.scriptsForm && this.scriptsForm.props.form.getFieldValue('sql')) {
        _loading = true
      }
      if (_loading) {
        notification.warning({
          top: 92,
          message: '存在未保存脚本,请点击确定保存,或点击取消放弃修改!',
          duration: 5
        })
        this.setState({
          loading: false
        })
        return
      }
      this.sqlverify(() => { // 验证成功
        this.setState({
          activeKey: val,
          loading: false
        })
      }, () => {             // 验证失败
        this.setState({
          loading: false
        })
      }, true)
    }
  }
  submitDataSource = () => {
    const { card } = this.props
    const { activeKey, setting, columns, scripts } = this.state
    return new Promise((resolve, reject) => {
      if (activeKey === 'setting') {
        this.settingForm.handleConfirm().then(res => {
          this.setState({
            setting: res
          }, () => {
            this.sqlverify(() => { resolve({uuid: card.uuid, setting: res, columns, scripts }) }, reject, false)
          })
        }, () => {
          reject()
        })
      } else if (activeKey === 'columns') {
        this.sqlverify(() => { resolve({uuid: card.uuid, setting, columns, scripts }) }, reject, false)
      } else if (activeKey === 'scripts') {
        let _loading = false
        if (this.scriptsForm && this.scriptsForm.state.editItem) {
          _loading = true
        } else if (this.scriptsForm && this.scriptsForm.props.form.getFieldValue('sql')) {
          _loading = true
        }
        if (_loading) {
          notification.warning({
            top: 92,
            message: '存在未保存脚本,请点击确定保存,或点击取消放弃修改!',
            duration: 5
          })
          reject()
          return
        }
        this.sqlverify(() => { resolve({uuid: card.uuid, setting, columns, scripts }) }, reject, false)
      }
    })
  }
  sqlverify = (resolve, reject, change = false, testScripts) => {
    const { searches } = this.props
    const { columns, setting, scripts } = this.state
    let _scripts = scripts.filter(item => item.status !== 'false')
    if (testScripts) {
      _scripts = testScripts.filter(item => item.status !== 'false')
    }
    if (!change && setting.interType === 'inner' && !setting.innerFunc && setting.execute === 'false' && _scripts.length === 0) {
      notification.warning({
        top: 92,
        message: '不执行默认sql时,请添加自定义脚本!',
        duration: 5
      })
      reject()
      return
    }
    if ((setting.interType === 'inner' && !setting.innerFunc && setting.execute !== 'false') || _scripts.length > 0) {
      let param = {
        func: 's_debug_sql',
        LText: SettingUtils.getDebugSql(setting, _scripts, columns, searches)
      }
      param.LText = Utils.formatOptions(param.LText)
      param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss') + '.000'
      param.secretkey = Utils.encrypt(param.LText, param.timestamp)
      Api.getLocalConfig(param).then(result => {
        if (result.status) {
          resolve()
        } else {
          reject()
          Modal.error({
            title: result.message
          })
        }
      })
    } else {
      resolve()
    }
  }
@@ -362,10 +459,11 @@
  }
  render() {
    const { columns, setting, scripts, colColumns, scriptsColumns, activeKey } = this.state
    const { columns, setting, scripts, colColumns, scriptsColumns, activeKey, loading } = this.state
    return (
      <div id="mob-verify-card-box-tab">
        {loading && <Spin size="large" />}
        <Tabs activeKey={activeKey} className="verify-card-box" onChange={this.changeTab}>
          <TabPane tab="数据源" key="setting">
            <SettingForm
@@ -373,6 +471,7 @@
              dict={this.props.dict}
              columns={columns}
              setting={setting}
              scripts={scripts}
              wrappedComponentRef={(inst) => this.settingForm = inst}
            />
          </TabPane>
@@ -400,6 +499,7 @@
              customScripts={scripts}
              systemScripts={this.state.systemScripts}
              scriptsChange={this.scriptsChange}
              scriptSubmit={this.scriptSubmit}
              wrappedComponentRef={(inst) => this.scriptsForm = inst}
            />
            <Table
src/mob/datasource/verifycard/index.scss
@@ -1,66 +1,74 @@
.verify-card-box {
  .ant-tabs-nav-scroll {
    text-align: center;
#mob-verify-card-box-tab {
  .ant-spin {
    position: absolute;
    left: calc(50% - 16px);
    top: 220px;
    z-index: 1;
  }
  .ant-tabs-content {
    min-height: 40vh;
  }
  table tr td {
    word-wrap: break-word;
    word-break: break-word;
  }
  .verify-form {
    .ant-input-number {
      width: 100%;
  .verify-card-box {
    .ant-tabs-nav-scroll {
      text-align: center;
    }
    .sql {
      .ant-col-sm-8 {
        width: 10.5%;
    .ant-tabs-content {
      min-height: 40vh;
    }
    table tr td {
      word-wrap: break-word;
      word-break: break-word;
    }
    .verify-form {
      .ant-input-number {
        width: 100%;
      }
      .ant-col-sm-16 {
        width: 89.5%;
      .sql {
        .ant-col-sm-8 {
          width: 10.5%;
        }
        .ant-col-sm-16 {
          width: 89.5%;
          padding-top: 4px;
        }
      }
      .sqlfield {
        .ant-form-item {
          margin-bottom: 5px;
        }
        .ant-form-item-control {
          line-height: 24px;
        }
        .ant-form-item-label {
          line-height: 25px;
        }
        .ant-form-item-children {
          line-height: 22px;
        }
        .ant-col-sm-8 {
          width: 10.5%;
        }
        .ant-col-sm-16 {
          width: 89.5%;
        }
      }
      .add {
        padding-top: 4px;
      }
    }
    .sqlfield {
      .ant-form-item {
        margin-bottom: 5px;
      }
      .ant-form-item-control {
        line-height: 24px;
      }
      .ant-form-item-label {
        line-height: 25px;
      }
      .ant-form-item-children {
        line-height: 22px;
      }
      .ant-col-sm-8 {
        width: 10.5%;
      }
      .ant-col-sm-16 {
        width: 89.5%;
      .anticon-question-circle {
        color: #c49f47;
        margin-right: 3px;
      }
    }
    .add {
      padding-top: 4px;
    .custom-table .ant-empty {
      margin: 20px 8px!important;
    }
    .anticon-question-circle {
      color: #c49f47;
      margin-right: 3px;
    .errorval {
      display: inline-block;
      width: 30px;
    }
  }
  .custom-table .ant-empty {
    margin: 20px 8px!important;
  }
  .errorval {
    display: inline-block;
    width: 30px;
  }
  .operation-btn {
    display: inline-block;
    font-size: 16px;
    padding: 0 5px;
    cursor: pointer;
    .operation-btn {
      display: inline-block;
      font-size: 16px;
      padding: 0 5px;
      cursor: pointer;
    }
  }
}
src/mob/datasource/verifycard/settingform/index.jsx
@@ -13,16 +13,16 @@
class SettingForm extends Component {
  static propTpyes = {
    type: PropTypes.string,      // 菜单类型
    dict: PropTypes.object,      // 字典项
    menuId: PropTypes.string,    // 菜单Id
    setting: PropTypes.object,   // 数据源配置
    formlist: PropTypes.array,   // 表单信息
    columns: PropTypes.array,    // 列设置
    scripts: PropTypes.array,    // 自定义脚本
  }
  state = {
    interType: 'inner',
    structure: 'array'
    interType: this.props.setting.interType || 'inner',
    structure: this.props.setting.structure || 'array'
  }
  handleConfirm = (otype) => {
@@ -31,10 +31,8 @@
    return new Promise((resolve, reject) => {
      this.props.form.validateFieldsAndScroll((err, values) => {
        if (!err) {
          values = {...setting, ...values}
          // 数据源前端验证
          if (values.interType === 'inner' && !values.innerFunc && values.default !== 'false' && !values.dataresource) {
          if (values.interType === 'inner' && !values.innerFunc && values.execute !== 'false' && !values.dataresource) {
            notification.warning({
              top: 92,
              message: '请填写内部函数或数据源!',
@@ -42,7 +40,7 @@
            })
            reject()
            return
          } else if (values.interType === 'inner' && !values.innerFunc && values.default !== 'false' && values.dataresource) {
          } else if (values.interType === 'inner' && !values.innerFunc && values.execute !== 'false' && values.dataresource) {
            let _quot = values.dataresource.match(/'{1}/g)
            let _lparen = values.dataresource.match(/\({1}/g)
            let _rparen = values.dataresource.match(/\){1}/g)
@@ -57,6 +55,7 @@
                message: '数据源中\'必须成对出现',
                duration: 5
              })
              reject()
              return
            } else if (_lparen !== _rparen) {
              notification.warning({
@@ -64,6 +63,7 @@
                message: '数据源中()必须成对出现',
                duration: 5
              })
              reject()
              return
            } else if (/--/ig.test(values.dataresource)) {
              notification.warning({
@@ -71,6 +71,7 @@
                message: '数据源中,不可出现字符 -- ,注释请用 /*内容*/',
                duration: 5
              })
              reject()
              return
            }
@@ -89,10 +90,8 @@
          // 数据源保存
          if (
            values.interType === 'inner' && !values.innerFunc &&
            values.default !== 'false' &&
            /[^\s]+\s+[^\s]+/ig.test(values.dataresource) &&
            setting.dataresource !== values.dataresource
            values.interType === 'inner' && !values.innerFunc && values.execute !== 'false' &&
            /[^\s]+\s+[^\s]+/ig.test(values.dataresource) && setting.dataresource !== values.dataresource
          ) {
            let param = {
              func: 's_DataSrc_Save',
@@ -107,17 +106,7 @@
            Api.getLocalConfig(param)
          }
          if (otype === 'change') {
            this.setState({
              setting: values,
            }, () => {
              resolve()
            })
          } else {
            values.customScript = this.getCustomScript(values)
            this.sqlverify(values, resolve, reject)
          }
          resolve(values)
        } else {
          reject(err)
        }
@@ -140,7 +129,7 @@
  }
  render() {
    const { columns } = this.props
    const { columns, setting } = this.props
    const { getFieldDecorator } = this.props.form
    const { interType, structure } = this.state
@@ -162,7 +151,7 @@
            <Col span={8}>
              <Form.Item label="名称">
                {getFieldDecorator('name', {
                  initialValue: '',
                  initialValue: setting.name,
                  rules: [
                    {
                      required: true,
@@ -175,7 +164,7 @@
            <Col span={8}>
              <Form.Item label="表名">
                {getFieldDecorator('tableName', {
                  initialValue: '',
                  initialValue: setting.tableName,
                  rules: [
                    {
                      required: true,
@@ -222,7 +211,7 @@
            {interType === 'inner' ? <Col span={8}>
              <Form.Item label="内部函数">
                {getFieldDecorator('innerFunc', {
                  initialValue: '',
                  initialValue: setting.innerFunc || '',
                  rules: [
                    
                  ]
@@ -232,7 +221,7 @@
            {interType === 'outer' ? <Col span={8}>
              <Form.Item label="接口地址">
                {getFieldDecorator('interface', {
                  initialValue: '',
                  initialValue: setting.interface || '',
                  rules: [
                    {
                      required: true,
@@ -245,14 +234,14 @@
            {interType === 'outer' ? <Col span={8}>
              <Form.Item label="外部函数">
                {getFieldDecorator('outerFunc', {
                  initialValue: '',
                  initialValue: setting.outerFunc || '',
                  rules: [
                  ]
                })(<Input placeholder={''} autoComplete="off" />)}
              </Form.Item>
            </Col> : null}
            <Col span={24} className="data-source" style={{paddingLeft: '7px'}}>
            {interType === 'inner' ? <Col span={24} className="data-source" style={{paddingLeft: '7px'}}>
              <Form.Item labelCol={{xs: { span: 24 }, sm: { span: 2 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 22 }} } label={
                <Tooltip placement="topLeft" title={'使用系统函数时,需填写数据源。注:数据权限替换符 $@ -> /* 或 \'\'、 @$ -> */ 或 \'\''}>
                  <Icon type="question-circle" />
@@ -260,17 +249,30 @@
                </Tooltip>
              }>
                {getFieldDecorator('dataresource', {
                  initialValue: ''
                  initialValue: setting.dataresource || ''
                })(<TextArea rows={4} />)}
              </Form.Item>
            </Col>
            </Col> : null}
            {interType === 'inner' ? <Col span={8}>
              <Form.Item label={
                <Tooltip placement="topLeft" title={'查询时,搜索条件以where条件拼接进入sql,统计时,将数据源中以“@+搜索字段+@”的内容,以搜索条件中的值进行替换后,提交查询,注:查询类型仅在使用系统函数时有效。'}>
                  <Icon type="question-circle" />
                  查询类型
                </Tooltip>
              }>
                {getFieldDecorator('queryType', {
                  initialValue: setting.queryType || 'query'
                })(
                <Radio.Group>
                  <Radio value="query">查询</Radio>
                  <Radio value="statistics">统计</Radio>
                </Radio.Group>)}
              </Form.Item>
            </Col> : null}
            {structure === 'array' ? <Col span={8}>
              <Form.Item label="主键">
                {getFieldDecorator('primaryKey', {
                  initialValue: '',
                  rules: [
                  ]
                  initialValue: setting.primaryKey || ''
                })(
                  <Select onChange={(value) => {this.selectChange('primaryKey', value)}}>
                    {columns.map((option, i) =>
@@ -285,20 +287,14 @@
            {structure === 'array' ? <Col span={8}>
              <Form.Item label="默认排序">
                {getFieldDecorator('order', {
                  initialValue: '',
                  rules: [
                  ]
                  initialValue: setting.order || ''
                })(<Input placeholder={'ID asc, UID desc'} autoComplete="off" />)}
              </Form.Item>
            </Col> : null}
            {structure === 'array' ? <Col span={8}>
              <Form.Item label="分页">
                {getFieldDecorator('laypage', {
                  initialValue: '',
                  rules: [
                  ]
                  initialValue: setting.laypage || 'true'
                })(
                <Radio.Group>
                  <Radio value="true">是</Radio>
@@ -306,13 +302,11 @@
                </Radio.Group>)}
              </Form.Item>
            </Col> : null}
            {interType === 'inner' ? <Col span={8}>
              <Form.Item label="默认sql">
                {getFieldDecorator('execute', {
                  initialValue: 'true',
                  rules: [
                  ]
                  initialValue: setting.execute || 'true'
                })(
                <Radio.Group>
                  <Radio value="true">执行</Radio>
@@ -323,10 +317,7 @@
            <Col span={8}>
              <Form.Item label="搜索条件">
                {getFieldDecorator('search', {
                  initialValue: 'true',
                  rules: [
                  ]
                  initialValue: setting.search || 'true'
                })(
                <Radio.Group>
                  <Radio value="true">接收</Radio>
src/mob/datasource/verifycard/utils.jsx
New file
@@ -0,0 +1,99 @@
export default class SettingUtils {
  /**
   * @description 生成页面查询语句
   * @return {String}  scripts       自定义脚本
   * @return {String}  searches      搜索条件
   * @return {Object}  setting       页面设置
   * @return {Array}   columns       显示字段
   */
  static getDebugSql (setting, scripts, columns, searches) {
    let sql = ''
    let _dataresource = ''
    let _customScript = ''
    let arr_field = columns.map(item => item.field).join(',')
    if (scripts.length > 0) {
      scripts.forEach(item => {
        _customScript += `
          ${item.sql}
        `
      })
    }
    if (_customScript) {
      _customScript = `declare @ErrorCode nvarchar(50),@retmsg nvarchar(4000) select @ErrorCode='',@retmsg =''
        ${_customScript}
      `
    }
    if (setting.interType === 'inner' && !setting.innerFunc && setting.execute !== 'false') {
      _dataresource = setting.dataresource
    }
    if (_dataresource) {
      _dataresource = _dataresource.replace(/@\$|\$@/ig, '')
    }
    if (_customScript) {
      _customScript = _customScript.replace(/@\$|\$@/ig, '')
    }
    // 正则替换
    let _regoptions = searches.map(item => {
      return {
        reg: new RegExp('@' + item.key + '@', 'ig'),
        value: `'${item.value}'`
      }
    })
    let _search = ''
    if (setting.queryType === 'statistics' && _dataresource) {
      _regoptions.forEach(item => {
        _dataresource = _dataresource.replace(item.reg, item.value)
      })
      _search = ''
    }
    if (_customScript) {
      _regoptions.push({
        reg: new RegExp('@orderBy@', 'ig'),
        value: setting.order
      })
      if (setting.laypage !== 'false') {
        _regoptions.push({
          reg: new RegExp('@pageSize@', 'ig'),
          value: 10
        }, {
          reg: new RegExp('@pageIndex@', 'ig'),
          value: 1
        })
      }
      _regoptions.forEach(item => {
        _customScript = _customScript.replace(item.reg, item.value)
      })
    }
    // 数据源处理, 存在显示列时
    if (arr_field && _dataresource) {
      if (/\s/.test(_dataresource)) {
        _dataresource = '(' + _dataresource + ') tb'
      }
      _dataresource = `select ${setting.laypage !== 'false' ?  'top 10' : ''} ${arr_field} from (select ${arr_field} ,ROW_NUMBER() over(order by ${setting.order}) as rows from ${_dataresource} ${_search}) tmptable ${setting.laypage !== 'false' ?  'where rows > 0' : ''} order by tmptable.rows`
    }
    if (_customScript) {
      sql = `${_customScript}
        ${_dataresource}
        aaa:
        if @ErrorCode!=''
          insert into tmp_err_retmsg (ID, ErrorCode, retmsg, CreateUserID) select @time_id@,@ErrorCode, @retmsg,@UserID@
      `
    } else {
      sql = _dataresource
    }
    return sql
  }
}
src/templates/zshare/formconfig.jsx
@@ -166,7 +166,7 @@
      key: 'queryType',
      label: Formdict['header.form.queryType'],
      initVal: setting.queryType || 'query',
      tooltip: '查询时,搜索条件以where条件拼接进入sql,统计时,将数据源中以“@+搜索字段”的内容,以搜索条件中的值进行替换后,提交查询,注:查询类型仅在使用系统函数时有效。',
      tooltip: '查询时,搜索条件以where条件拼接进入sql,统计时,将数据源中以“@+搜索字段+@”的内容,以搜索条件中的值进行替换后,提交查询,注:查询类型仅在使用系统函数时有效。',
      required: false,
      readonly: false,
      options: [